AngularJs. Cycle in $scope.$watch - angularjs

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>

Related

Showing dynamic content inside ngRepeat

Struggling to show dynamic content inside a ngRepeat. When it comes time to show my promise content, I'm getting an empty object {}:
<div ng-controller="DemoCtrl">
<div class="sidebar" ng-repeat="row in rows">
<div class="row">
<input type="checkbox">
<div class="name">{{row.name}}</div>
<div class="title">{{map[$index]}}</div>
</div>
</div>
</div>
and the controller:
function DemoCtrl($scope, $http, $q) {
const rows = function() {
const rows = [];
for (let i = 0; i < 12; i++) {
rows.push({
id: `demo-${i}`,
name: `Demo ${i}`
});
}
return rows;
};
$scope.rows = rows();
$scope.map = [];
// $scope.$watch($scope.map, function (oldValue, newValue) {
// console.log(oldValue, newValue);
// });
function _data() {
// const promises = [];
for (let i = 0; i < $scope.rows.length; i++) {
var defer = $q.defer();
$http.get(`https://jsonplaceholder.typicode.com/posts/${i + 1}`).then(function(post) {
defer.resolve(`${post.data.title.substring(0, 10)}...`);
});
$scope.map.push(defer.promise);
// promises.push(defer.promise);
}
// return $q.all(promises);
return $q.all($scope.map);
}
function _init() {
_data().then(function(data) {
$scope.map = data; // why aren't we getting here?
});
};
_init();
}
Plunker here: https://plnkr.co/edit/2BMfIU97Moisir7BBPNc
I've tinkered with some other ideas such as trying to add a $watch on the $scope object after the value changes, but I'm not convinced this will help in any way. Some lingering questions I have:
From what I understand, you can use a promise inside a template so how/why does this change inside a ngRepeat?
Why isn't my callback for $q.all getting called?
If this is not the right approach, what is?
In Angular you will almost never need to use $q.
You can simply fill an array of posts titles after each $http.get
function DemoCtrl($scope, $http) {
const rows = function () {
const rows = [];
for (let i = 0; i < 12; i++) {
rows.push({
id: `demo-${i}`,
name: `Demo ${i}`
});
}
return rows;
};
$scope.rows = rows();
$scope.map = [];
function _init() {
for (let i = 0; i < $scope.rows.length; i++) {
$http.get(`https://jsonplaceholder.typicode.com/posts/${i + 1}`).then(function (post) {
$scope.map.push(post.data.title);
});
}
}
_init();
}
https://plnkr.co/edit/zOF4KNtAIFqoCOfinaMO?p=preview

variable didn't change while another variable changes

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>

Alternative of ng-repeat in the AngularJS?

I have an array in which the thousands products and i have iterate the array with the help of the ng-repeat,it is working properly in browser,but in the mobile devices products are load really slow so how to improve the performance time of the products on mobile devices.
You should use lazy-load concept. I mean on scroll or on clicking any button, let load some number of rows of data.
For example:
In First API call, load 20 rows, then again 20+20 using API call.
There are lots of modules available like:
See some live examples ngInfiniteScroll
or you can create your own.
.controller('NoticeCtrl', function($scope, $stateParams, $state, $http, NoticeService, baseUrl) {
$scope.items = [];
NoticeService.loadNotice().then(function(items) {
if(items != 0)
{
$scope.items = items;
} else {
$scope.noMoreItemsAvailable = true;
}
});
$scope.noMoreItemsAvailable = false;
$scope.numberOfItemsToDisplay = 5;
$scope.limit = 0;
$scope.loadMore = function(limit) {
var start;
var limit;
var j;
for(var i= limit, j=0; j < $scope.numberOfItemsToDisplay; i++,j++)
{
start = i+ 0;
limit = $scope.numberOfItemsToDisplay;
}
$scope.limit = $scope.limit + $scope.numberOfItemsToDisplay;
NoticeService.refreshNotice(start, limit).then(function(items){
if(items != 0)
{
$scope.items = $scope.items.concat(items);
} else {
$scope.noMoreItemsAvailable = true;
}
$scope.$broadcast('scroll.infiniteScrollComplete');
});
};
})
Factory code
.factory('NoticeService', function($http , $stateParams, baseUrl){
var BASE_URL = baseUrl+"api_method=notice.list&api_version=1.0&app_key=12345&user_id="+$stateParams.userId
var items = [];
return {
loadNotice: function(){
var start = 0;
var limit = 4;
return $http.get(BASE_URL+"&start="+start+"&limit="+limit).then(function(response){
items = response.data.responseMsg;
return items;
});
},
refreshNotice: function(starts, limits){
return $http.get(BASE_URL+"&start="+starts+"&limit="+limits).then(function(response){
items = response.data.responseMsg;
return items;
});
}
}
})
Your HTML part
<ion-item class="content double-padding" style="white-space: normal;" ng-repeat="item in items">
<div class="text-right">{{item.createdAt}}</div>
<h2>{{item.title}}</h2>
{{item.content}}
</ion-item>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore(limit)" distance="5%"></ion-infinite-scroll>
I hope this will help you :-)

md-checkbox does not work with ng-click

I want to save position each time when I change checkbox:
<h1 class="md-display-2">Simple TODO ng app</h1>
<h2 class="md-display-3"></h2>
<div ng-include src="'todo/add.html'"></div>
<div>
<div layout="row">
<div flex class="md-title">Scope</div>
<div flex="10" class="md-title">Till date</div>
<div flex="10" class="md-title">Is reached?</div>
<div flex="10" class="md-title">
<span ng-click="todoctrl.show_add()" class="material-icons controls">add</span>
</div>
</div>
<div layout="row" ng-repeat="todo in todoctrl.todos track by $index">
<div flex ng-class="{true:'striked', false:'simple'}[todo.reached]">{{todo.name}}</div>
<div flex="10">
{{todo.tillDate | date:'dd/MM/yyyy'}}
</div>
<div flex="10">
<md-checkbox ng-model="todo.reached" aria-label="Is reached" ng-click="todoctrl.changeState(todo.name)"></md-checkbox>
</div>
<div flex="10">
<span ng-click="todoctrl.deleteScope(todo.name)"
class="material-icons controls">clear</span>
</div>
</div>
</div>
In this case controller is touched (I tried with to debug with console log), but the checkbox value is not changed before page reload. After reload the value is checkbox is presented as expected.
If I remove ng-click="todoctrl.changeState(todo.name)" then checkbox is working good, but no info is sent to controller.
This is my service:
(function() {
'use strict';
angular.module('app').service('ToDoService', ToDoService);
ToDoService.$inject = ['JsonService'];
function ToDoService(JsonService) {
return {
deleteScope : deleteScope,
submitScope : submitScope,
changeState : changeState,
getData : getData
}
function getData() {
var todos = JsonService.getData();
return todos;
}
function deleteScope(arr, scope) {
arr.splice(findElementByScope(arr, scope), 1);
JsonService.setData(arr);
}
function submitScope(arr, scope, tillDate) {
var newTodo = {};
newTodo.name = scope;
newTodo.reached = false;
newTodo.tillDate = tillDate;
arr.push(newTodo);
JsonService.setData(arr);
}
function changeState(arr, scope) {
console.log("Service change state for scope: " + scope);
var todo = {};
var index = findElementByScope(arr, scope);
todo = arr[index];
todo.reached = !todo.reached;
JsonService.setData(arr);
}
function findElementByScope(arr, scope) {
for (var i = arr.length; i--;) {
if (arr[i].name == scope) {
return i;
}
}
return -1;
}
}
})();
And this is the Controller:
(function() {
'use strict';
angular.module('app').controller('ToDoController', ToDoController);
function ToDoController(ToDoService) {
var vm = this;
vm.show_form = false;
vm.todos = ToDoService.getData();
vm.scope = '';
vm.show_add = show_add;
vm.submitScope = submitScope;
vm.deleteScope = deleteScope;
vm.changeState = changeState;
function show_add() {
console.log("Controller show add");
vm.show_form = true;
}
function submitScope() {
ToDoService.submitScope(vm.todos, vm.scope, vm.tillDate);
vm.show_form = false;
vm.scope = '';
}
function deleteScope(scope) {
ToDoService.deleteScope(vm.todos, scope);
}
function changeState(scope) {
ToDoService.changeState(vm.todos, scope);
}
}
})();
Use ng-change instead of ng-click
<md-checkbox ng-model="todo.reached" aria-label="Is reached" ng-change="todoctrl.changeState(todo.name, todo.reached)"></md-checkbox>
ng-change trigger after value change in model

Increasing a vote (in a list of saved URLs) doesn't work

I have a list of URLs saved in a firebase DB, and I'm trying to simply add a count next to each url, so that users can like them. My $scope.increase function tries to serve that purpose but there must be something wrong, it should increase the count on click and also update the database. Can anyone help?
HTML
<li ng-repeat="url in urls | filter:todoSearch" class="list-item">
<div class="row">
<div class="col-md-8 link-col">
<a href="{{url.title}}" class="link">
<p class="title">{{url.name}}</p>
<p class="url">{{url.title}}</p>
</a>
<p ng-model="mvLikes" ng-click="increase($index)">0</p>
</div>
</div>
</li>
JS
var urlFire = angular.module("UrlFire", ["firebase"]);
function MainController($scope, $firebase) {
$scope.favUrls = $firebase(new Firebase('https://lloydyapp.firebaseio.com/'));
$scope.urls = [];
$scope.favUrls.$on('value', function() {
$scope.urls = [];
var mvs = $scope.favUrls.$getIndex();
for (var i = 0; i < mvs.length; i++) {
$scope.urls.unshift({
name: $scope.favUrls[mvs[i]].name,
title: $scope.favUrls[mvs[i]].title,
likes: $scope.favUrls[mvs[i]].likes,
key: mvs[i]
});
};
});
$scope.increase = function(index) {
$scope.mvLikes += 1;
var mvLikes = $scope.mvLikes;
var mv = $scope.urls[index];
var updateUrlRef = buildEndPoint(mv.key, $firebase);
updateUrlRef.$set({
likes: mvLikes
});
}
....
function buildEndPoint(key, $firebase) {
return $firebase(new Firebase('https://lloydyapp.firebaseio.com/' + key));
}

Resources