I have the following code for creating a slider:
<html ng-app="angular-bootstrap-slider-test">
<head>
<title>Angular Bootstrap Slider test</title>
<script data-require="angular.js#1.3.0" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script>
<script data-require="jquery#*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-slider.css" rel="stylesheet" />
</head>
<body ng-controller="TestCtrl">
<div class="col-md-2 col-md-offset-2">
<slider on-stop-slide="executeMe();" ng-model="sliders.sliderValue" min="{{testOptions.min}}" step="{{testOptions.step}}" max="{{testOptions.max}}"></slider>
{{myFormater(sliders.sliderValue)}}
</div>
<script type="text/javascript" src="bootstrap-slider.js"></script>
<!-- angular-slider include -->
<script type="text/javascript" src="slider.js"></script>
<!-- test file include -->
<script src="app.js">
</script>
angular.module('angular-bootstrap-slider-test', ['ui.bootstrap-slider'])
.controller('TestCtrl', ['$scope', function($scope) {
$scope.sliders = {};
$scope.sliders.sliderValue = 50;
$scope.testOptions = {
min: 0,
max: 100,
step: 1,
};
$scope.sliders.thirdSliderValue = 0;
$scope.myFormater = function(value) {
return value + "%";
}
$scope.executeMe = function() {
console.log('done');
}
}]);
What i'm trying to do with no success is to execute a function when the user finishis to to move the slider
here is the code on plunker:
http://plnkr.co/edit/iULltHh0fRAbvuoFu84t?p=preview
Thanks allot
Avi
You can use ngMouseup for that.
<div class="col-md-2 col-md-offset-2" ng-mouseup="executeMe()">
<slider ng-model="sliders.sliderValue" min="{{testOptions.min}}" step="{{testOptions.step}}" max="{{testOptions.max}}"></slider>
{{myFormater(sliders.sliderValue)}}
</div>
Here's your plunkr modified to demonstrate.
Update
A different approach will be to $watch the slider's value. You can set a timeout so you don't trigger your function while sliding, but only when the value has not changed for some time.
var timeout;
$scope.$watch('sliders.sliderValue', function() {
if (timeout) {
$timeout.cancel(timeout);
}
timeout = $timeout($scope.executeMe,200);
});
See example
Related
I am trying to make a button that executes a action immediately after he was clicked. But if the mouse is still down after a timeout the action should be repeated as long as the button is down.
In the following code the $interval is working. But somehow the $timeout gets ignored and the interval starts immediately. What am I doing wrong?
angular
.module('myApp', [])
.controller('myController', ($scope, $timeout, $interval) => {
var interval;
var timeout;
let main = $scope;
main.times = 0;
let promise;
let doSomethingOneTime = () => {
$scope.times++;
};
let doSomethingInfinitely = function() {
promise = $interval(function() {
doSomethingOneTime();
}, 100)
};
main.mouseDown = function(action) {
doSomethingOneTime();
$timeout(doSomethingInfinitely, 5000);
};
main.mouseUp = function() {
$interval.cancel(promise);
};
});
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="script.ts"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="system.config.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="tsconfig.json"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller='myController'>
<button ng-mousedown="mouseDown()" ng-mouseup="mouseUp()">Mouse Down</button>
<br>
<span>Doing something {{times}} times</span>
</body>
</html>
The problem is two fold. The first case is that if you mouse up before the timeout delay has finished, the interval promise you set will still be undefined, thus when you call cancel nothing is cancelled. The second problem is if you click the button twice you will lose all reference to the first interval promise. The second click, which creates a second timeout will replace the first interval promise when it finishes. In effect you'll have 2 $intervals executing concurrently, one of which you have no reference to.
Here is a working example.
angular
.module('myApp', [])
.controller('myController', ($scope, $timeout, $interval) => {
var interval;
var timeout;
$scope.times = 0;
$scope.mouseUp = function(){
$timeout.cancel(timeout);
$interval.cancel(interval);
};
let increment = ()=>{
$scope.times++;
};
$scope.mouseDown = function(){
increment();
timeout = $timeout(()=>{
interval = $interval(()=>{
increment();
},100)
}, 1000)
};
});
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="script.ts"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="system.config.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="tsconfig.json"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller='myController'>
<button ng-mousedown="mouseDown()" ng-mouseup="mouseUp()">Mouse Down</button>
<br>
<span>Doing something {{times}} times</span>
</body>
</html>
I am trying to populate input by typing the number in input[number].
Why this doesn't work
// Code goes here
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.lengInput = {
count: 0,
values: [],
fill: function(limit) {
var sequence = [];
for (var i = 0; i < limit; i++) {
sequence.push(i);
}
return sequence;
}
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.js" data-semver="1.5.11"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<input ng-model="lengInput.count" type="number" min="1" max="20">
<ul>
<li ng-repeat="i in lengInput.fillSequence(lengInput.count)">
<input ng-model="lengInput.values[i]" />
</li>
</ul>
</body>
</html>
since this is working
JSFiddle Demo
Please find my mistake.
Instead of attaching the function directly to the ng-repeat, you can use ng-init to intialize the $scope.lengInput.values and add an ng-change to the input field where $scope.lengInput.count is getting set, so that the function does not get run every time, instead it runs only when the value in the input box has changed!
// Code goes here
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.lengInput = {
count: 0,
values: [],
fill: function(limit) {
var sequence = [];
for (var i = 0; i < limit; i++) {
sequence.push(i);
}
$scope.lengInput.values = sequence;
}
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.js" data-semver="1.5.11"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl" ng-init="lengInput.fill(lengInput.count)">
<p>Hello {{name}}!</p>
<input ng-model="lengInput.count" type="number" min="1" max="20" ng-change=" lengInput.fill(lengInput.count)">
<ul>
<li ng-repeat="i in lengInput.values">
<input ng-model="lengInput.values[i]" />
</li>
</ul>
</body>
</html>
Say I've got AdamController as adam and AnujController as anuj. I want anuj.anujProp to have a j appended to it every time adam.adamProp changes.
How could this be done? What is the best way?
Here are 4 possible ways that I came up with. I ranked them in the order that I personally feel is best.
Events - http://plnkr.co/edit/4AD8e47DaOSuutrphIkN?p=preview
Method on a Factory - http://plnkr.co/edit/Vixab8LjDtow5YYfnlMV?p=preview
Factory + $watch - http://plnkr.co/edit/1zVZ9EDarCGPOMZvrJMd?p=preview
$scope inheritance - http://plnkr.co/edit/3b7tzPI5Y4CcwWYXUk25?p=preview
The $scope inheritance approach just feels "messy". I like the event driven approach over the factory approaches because I feel like there's a sort of overhead associated with the factories, and if it's only going to be used for this one purpose, the overhead isn't worth it. Plus, this just seems to be exactly what events are for. I put (2) ahead of (3) because the $watch hurts performance.
Events
angular
.module('app', [])
.controller('AdamController', AdamController)
.controller('AnujController', AnujController)
;
function AdamController($rootScope) {
var vm = this;
vm.prop = 'adam';
vm.update = function() {
$rootScope.$broadcast('propChange');
};
}
function AnujController($scope) {
var vm = this;
vm.prop = '';
$scope.$on('propChange', function(event) {
event.currentScope.anuj.prop += 'x';
});
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script data-require="angular.js#1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller='AdamController as adam'>
<input ng-model='adam.prop' ng-change='adam.update()'>
</div>
<div ng-controller='AnujController as anuj'>
<p>{{ anuj.prop }}</p>
</div>
</body>
</html>
Method on a Factory
angular
.module('app', [])
.factory('Factory', Factory)
.controller('AdamController', AdamController)
.controller('AnujController', AnujController)
;
function Factory() {
return {
anujProp: 'anuj',
update: function() {
this.anujProp += 'j';
}
};
}
function AdamController(Factory) {
var vm = this;
vm.factory = Factory;
}
function AnujController(Factory) {
var vm = this;
vm.factory = Factory;
}
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script data-require="angular.js#1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller='AdamController as adam'>
<input ng-model='initial' ng-change='adam.factory.update()'>
</div>
<div ng-controller='AnujController as anuj'>
<p>{{ anuj.factory.anujProp }}</p>
</div>
</body>
</html>
Factory + $watch
angular
.module('app', [])
.factory('Factory', Factory)
.controller('AdamController', AdamController)
.controller('AnujController', AnujController)
;
function Factory() {
return {
shared: 'shared',
related: 'related'
};
}
function AdamController(Factory) {
var vm = this;
vm.factory = Factory;
}
function AnujController(Factory, $scope) {
var vm = this;
vm.factory = Factory;
$scope.$watch('anuj.factory.related', function(newValue, oldValue, scope) {
scope.anuj.factory.related = newValue.toUpperCase();
});
}
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script data-require="angular.js#1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller='AdamController as adam'>
<input ng-model='adam.factory.shared'>
<input ng-model='adam.factory.related'>
</div>
<div ng-controller='AnujController as anuj'>
<p>{{ anuj.factory.shared }}</p>
<p>{{ anuj.factory.related }}</p>
</div>
</body>
</html>
$scope inheritance
angular
.module('app', [])
.controller('AdamController', AdamController)
.controller('AnujController', AnujController)
;
function AdamController($scope) {
var vm = this;
vm.adamProp = 'adam';
vm.update = function() {
var anuj = $scope.$parent.$$childTail.anuj;
anuj.anujProp += 'j';
};
}
function AnujController() {
var vm = this;
vm.anujProp = 'anuj';
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller="AdamController as adam">
<input ng-model="adam.adamProp" ng-change="adam.update()" />
</div>
<div ng-controller="AnujController as anuj">
<p>{{ anuj.anujProp }}</p>
</div>
</body>
</html>
html file:
<html ng-app="IDAddon" ng-csp>
<head>
<link rel="stylesheet" type="text/css" href="styles/angular-csp.css">
<script src="lib/angular.min.js"></script>
<script src="scripts/app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div id="somepopup">
Delayed Message: {{textmessage}}
</div>
</body>
</html>
app.js script:
function MainController($scope, suggestionService) {
$scope.getMessage = function() {
window.addEventListener("message", function (){
$scope.$apply(function() {
$scope.textmessage = 'Fetched after 3 seconds';
});
} , false);
}
$scope.getMessage();
}
var IDmodule = angular.module('IDAddon', []).controller('MainCtrl', MainController)
I can confirm that the "message" event is received and the event handler function is called, but the page never gets updated with the message.
Am I missing anything here?
Why does this not work for me? Based on this question How to Integrate Flot with AngularJS?
All I get is a blank page.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="static/js/angular/angular.min.js"></script>
<script type="text/javascript" src="static/js/flot/jquery.flot.js"></script>
<script type="text/javascript" src="static/js/jquery/jquery-2.1.0.js"></script>
<script type="text/javascript" src="static/lib/flot/controller.js"></script>
<style type='text/css'>
chart {
display:none;
width:400px;
height:200px;
}
</style>
</head>
<body>
<div ng-app='App'>
<div ng-controller='Ctrl'>
<chart ng-model='data'></chart>
</div>
</div>
</body>
</html>
#Controller.js
var App = angular.module('App', []);
App.controller('Ctrl', function ($scope) {
$scope.data = [[[0, 1], [1, 5], [2, 2]]];
});
App.directive('chart', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var data = scope[attrs.ngModel];
$.plot(elem, data, {});
elem.show();
}
};
});
You included the scripts in the wrong order. It should be jQuery, Flot, and then angular (followed by your controller):
<script data-require="jquery#*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="flot#*" data-semver="0.8.2" src="//cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.min.js"></script>
<script data-require="angular.js#1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
Here is a plunker: http://plnkr.co/edit/WI3lXKRxxEpPvnhHfgrf?p=preview