variable didn't change while another variable changes - angularjs

I'm trying to convert sessionlength to seconds and save it in a variable called totalTime (totalTime = sessionlength * 60).
In my script, user can click the button to increase/decrease sessionlength.
But the problem is totalTime didn't change with sessionlegnth changed.
Can anyone point out where did I go wrong? thanks in advance!
var myApp = angular.module('myApp', []);
myApp.controller('pomodoroTimer',function pomodoroTimer($scope) {
$scope.breaklength = 5;
$scope.sessionlength = 25;
$scope.totalTime = $scope.sessionlength * 60;
$scope.decreaseNumber = function() {
$scope.sessionlength--;
};
$scope.increaseNumber = function() {
$scope.sessionlength++;
};
});

You are not recalculating the total time after session length changes, You can do it like this:-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.breaklength = 5;
$scope.sessionlength = 25;
$scope.calcTotalTime = function(){
$scope.totalTime = $scope.sessionlength * 60;
}
$scope.decreaseNumber = function() {
$scope.sessionlength--;
$scope.calcTotalTime();
};
$scope.increaseNumber = function() {
$scope.sessionlength++;
$scope.calcTotalTime();
};
$scope.calcTotalTime();
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="increaseNumber()">Increase</button>
<button ng-click="decreaseNumber()">Decrease</button>
<br>
Session Length:{{sessionlength}}<br>
Total Time:{{totalTime}} <br>
</div>

Related

How to use angular.bind(self, fn, args)

I am new to angular js. I was gone through the angular api references,
I had seen function called angular.bind(self, fn, args).
I could not understand the usage of this function. Can anyone explain this function with one example?
It used in Function Currying. An example with JavaScript:
var concat = function(input1) {
return function(input2) {
console.log(input1 + ", " + input2);
};
};
var externalFunction = concat("Hello");
externalFunction("World!"); // gives: "Hello, World!"
This allows you to use only some parameters and not all, for example concant("Hello") instead of concant("Hello","World!"). You can imagine using a defined variable as one of the parameters, whereas you fill in the second one from a user input. The same concept can be used with AnuglarJS:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
</head>
<body ng-app="app">
<div ng-controller="bindController">
<input type="number" ng-model="num" ng-change="AddValue()" />
Adding 5: {{Add}}
</div>
</body>
</html>
<script>
var app = angular.module("app", []);
app.controller('bindController',['$scope',function($scope){
$scope.num = 30;
$scope.AddValue = function () {
var addData = angular.bind(this, function (a, b) {return a + b;});
$scope.Add = addData(5, $scope.num);
}
$scope.AddValue();
}]);
</script>
Controller
app.controller('Identity`enter code here`Controller', ['$scope',
function($scope) {
$scope.Name = "";
$scope.Result = "";
var greet = function (greeting, punctuation) {
$scope.Result = greeting + ' ' + $scope.Name +''+ punctuation;
};
$scope.callBind = function () {
var bound = angular.bind(this, greet, 'Welcome');
bound('!!!!!');
};
}]);
html
<fieldset style="background-color:#DDE4E9;">
<legend>AngulerJS $scope.bind() Example</legend>
<div ng-controller="IdentityController">
<p>{{Result}}</p>
<input ng-model="Name">
<button ng-click="callBind()">Call Bind</button>
</div>
</fieldset>
I Think Its Working

How to wrap this controller logic inside a angular function and use it in select html element

How to wrap this controller logic inside a angular function and use it in select html element. Here inside controller code is use as inline logic without function.
Controller:
var year = new Date().getFullYear();
var range = [];
range.push(year);
for(var i=1;i<20;i++) {
range.push(year + i);
}
$scope.years = range;
View:
<select ng-options="year for year in years">
</select>
You can declare a function like that :
$scope.myfunction = function(){
var year = new Date().getFullYear();
var range = [];
range.push(year);
for(var i=1;i<20;i++) {
range.push(year + i);
}
return range;
}
and in your HTML :
<select ng-model="selectedYear" ng-options="year for year in myfunction()"></select>
I think all you are missing is the ng-model from the select statement. Here is a working example:
(function() {
angular
.module("app", []);
angular
.module("app")
.controller("AppController", AppController);
AppController.$inject = ["$scope"];
function AppController($scope) {
var vm = this;
vm.selectedYear = "";
vm.years = [];
loadData();
function loadData() {
var year = new Date().getFullYear();
var range = [];
range.push(year);
for (var i = 1; i < 20; i++) {
range.push(year + i);
}
vm.years = range;
}
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.6.1" data-semver="1.6.1" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="AppController as vm">
<div>
<select ng-model="vm.selectedYear"ng-options="year for year in vm.years">
</select>
</div>
</body>
</html>

AngularJS - ng-click is calling multiple times

I'm new to AngularJS and have been learning it from W3Schools. My issue is that ng-click is not working properly. It's calling repeatedly. If I click on the element with ng-click once it calls the function once. If I click it again it calls the function twice. If I continue clicking the button the function is called as many times as I've clicked the element before.
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<h1 id="h12" ng-click="changeName()" style="cursor:pointer;">{{firstname}}</h1>
</div>
<script>
var count = 0;
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstname = "John";
$scope.changeName = function() {
var h12 = document.getElementById("h12").innerHTML;
alert(count);
if (count == 0) {
$scope.firstname = "Nelly";
changeNGClick(h12);
count++;
} else {
count++;
var x = "";
var div1 = document.getElementById("h12");
var align = div1.getAttribute("data-v");
alert(align);
$scope.firstname = align;
changeNGClick(h12);
}
}
return false;
});
function compile(element) {
var el = angular.element(element);
$scope = el.scope();
$injector = el.injector();
$injector.invoke(function($compile) {
$compile(el)($scope)
})
}
function changeNGClick(v) {
var el = document.getElementById("h12");
el.setAttribute("data-v", v);
compile(el);
}
</script>
<p>Click on the header to run the "changeName" function.</p>
<p>This example demonstrates how to use the controller to change model data.</p>
</body>
</html>
This is how the code will work. When I click the header which has the text John then it will change to display Nelly. If you click it again it should change back to John. The value will be saved on the <h1> tags data-v. I would also appreciate another way of doing this if you have any suggestions.

AngularJs. Cycle in $scope.$watch

I can't understand whats wrong. I need create array of hours and minutes and show him.
HTML:
<div ng-app="test">
<div ng-controller="timeCtrl" ng-init="opentime='9';closetime='24'">
<div ng-repeat="time in times">
{{time}}
</div>
</div>
</div>
JS:
var app = angular.module('test', []);
app.controller('timeCtrl', ['$scope', function ($scope) {
$scope.$watch('opentime', function () {
$scope.times = [];
for (var hours = $scope.opentime; hours < $scope.closetime; hours++) {
console.log(hours);
for (var minutes = 0; minutes < 4; minutes++) {
var linkMinutes = minutes * 15;
if (linkMinutes === 0) {
linkMinutes = "00";
}
console.log(linkMinutes);
$scope.times.push(hours + ':' + linkMinutes);
}
}
});
}])
Why console.log is empty, but vars opentime and closetime with value?
Fiddle: http://jsfiddle.net/Zoomer/mj8zv2qL/
that because your scope variable opentime never been changed to fire watcher
I'v updated the example and simulated the variable change
scope.$watch will execute only when opentime change value please see more here https://docs.angularjs.org/api/ng/type/$rootScope.Scope
and that demo http://jsfiddle.net/oprhy6te/enter link description here
CTRL:
app.controller('timeCtrl', ['$scope', function ($scope) {
$scope.$watch('opentime', function () {
$scope.updateTimes();
});
$scope.updateTimes = function () {
$scope.times = [];
for (var hours = $scope.opentime; hours < $scope.closetime; hours++) {
console.log(hours);
for (var minutes = 0; minutes < 4; minutes++) {
var linkMinutes = minutes * 15;
if (linkMinutes === 0) {
linkMinutes = "00";
}
console.log(linkMinutes);
$scope.times.push(hours + ':' + linkMinutes);
}
}
}
function activate() {
$scope.opentime = 9;
$scope.closetime = 13;
$scope.updateTimes();
}
activate();
}])
HTML:
<div ng-app="test">
<div ng-controller="timeCtrl">
<input type="text" ng-model="opentime" />
<div ng-repeat="time in times"> {{time}}
</div>
</div>
</div>

How does service variable change update to controllers

I have a small problem and I don't understand this thing:
When I add an item to TestiFactorys arr - array it does update to both controllers
On the other hand why does not TestiFactorys arr_len update to both controllers. And in TestiController why do I have to "manually" update TestControllers list1_length to make it update to view but I don't have to update TestiContollers list1 to make it update to view
I am assuming that my poor Javascript or Javascript variable scope understanding is causing this but i just don't see it.
I am using AngularJS version 1.2.16
<!DOCTYPE html>
<html ng-app="TestiApp">
<head>
<title></title>
</head>
<body>
<div ng-controller="TestController">
List items from controller: {{list1}}<br>
List item count:{{list1_length}}
<input type="text" ng-model="param"><br>
<button ng-click="list1_add(param)">asd</button>
</div>
<br><br>
<div ng-controller="TestController2">
List items from controller2{{list2}} <br>
List items count in from controller2: {{list2_length}}
</div>
<script src="scripts/angular.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
And this is my app.js:
var TestiApp = angular.module('TestiApp', [])
TestiApp.factory('TestiFactory',function() {
var arr = ['abx','cbs'];
var arr_len = arr.length;
return {
list : function() {
return arr;
},
add_to_arr : function(n) {
arr.push(n);
},
arr_len : function() {
arr_len = arr.length;
return arr_len;
}
}
}
);
TestiApp.controller('TestController', function($scope, TestiFactory) {
$scope.list1 = TestiFactory.list();
$scope.list1_length = TestiFactory.arr_len();
$scope.list1_add = function (d) {
TestiFactory.add_to_arr(d);
$scope.param = '';
$scope.list1_length = TestiFactory.arr_len();
}
});
TestiApp.controller('TestController2', function($scope, TestiFactory) {
$scope.list2 = TestiFactory.list();
$scope.list2_length = TestiFactory.arr_len();
});
EDIT WITH SOLUTION
Here is working solution. Based to comments I decided to do more studying on Javascripts basics which
is of course the thing I should have done before trying to use this complex framework which uses Javascript. So now I have some basic understanding how to use references in Javascript and what primitive data types are. And based on that here is working version:
<!DOCTYPE html>
<html ng-app="TestiApp">
<head>
<title></title>
</head>
<body>
<div ng-controller="TestController">
List items from controller: {{list1()}}<br>
List item count:{{list1_len()}}
<input type="text" ng-model="param"><br>
<button ng-click="list1_add(param)">asd</button>
</div>
<br><br>
<div ng-controller="TestController2">
List items from controller2{{list2()}} <br>
List items count in from controller2: {{list2_length()}}
</div>
<script src="scripts/angular.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
And app.js:
var TestiApp = angular.module('TestiApp', [])
TestiApp.factory('TestiFactory',function() {
var arr = ['abx','cbs'];
return {
list : function() {
return arr;
},
add_to_arr : function(n) {
arr.push(n);
},
arr_len : function() {
return arr.length;
}
}
}
);
TestiApp.controller('TestController', function($scope, TestiFactory) {
$scope.list1 = TestiFactory.list;
$scope.list1_add = TestiFactory.add_to_arr;
$scope.list1_len = TestiFactory.arr_len;
});
TestiApp.controller('TestController2', function($scope, TestiFactory) {
$scope.list2 = TestiFactory.list;
$scope.list2_length = TestiFactory.arr_len;
});
I've ran into this many times. Factories and services in angular are not like scopes...they work using references. The reason the array updates in your controllers is because the original reference was updated. The length is not updating because the number type is primitive.
This should work:
TestiApp.controller('TestController', function($scope, TestiFactory) {
$scope.list1 = TestiFactory.list();
$scope.$watch('list1', function(list1) {
$scope.list1_length = list1.length;
});
$scope.list1_add = function (d) {
TestiFactory.add_to_arr(d);
$scope.param = '';
};
});
TestiApp.controller('TestController2', function($scope, TestiFactory) {
$scope.list2 = TestiFactory.list();
$scope.$watch('list2', function(list2) {
$scope.list2_length = list2.length;
});
});

Resources