i was trying to pass the list of value when page is loaded. but my ng-init function not even getting trigger. whats the problem with my code.
<li class="tag" ng-repeat="list in displayItems track by $index" ng-class="{selected: $index==selectedIndex}" data-ng-init="display(selecteditemslist,searchid)">
<span class="tag-label">{{list}}</span><span class="tag-cross pointer" ng-click="Delete($index,selecteditemslist[$index],list,searchid)">x</span>
</li>
to the function in controller
$scope.display=function(list,searchid){
console.clear();
console.info(list);
console.info(searchid);
switch(searchid) {
case 'organisation' :
for(var i=0; i<list.length; i++){
getOrg(list[i]).fetch({}).$promise.then(
function (value) {
$scope.displayItem = value.data[0];
console.clear();
console.info($scope.displayItem);
$scope.displayItems.push($scope.displayItem.displayConfig[0].propertyValue);
//$scope.displayItems = $scope.displayItem.displayConfig[0].propertyValue;
console.info($scope.displayItems);
});
}
break;
case 'people' :
for(var j=0; j<list.length; j++) {
getPeople(list[j]).fetch({}).$promise.then(
function (value) {
$scope.displayItem = value.data[0];
console.info($scope.displayItem);
$scope.displayItems.push($scope.displayItem.displayConfig[0].propertyValue);
//$scope.displayItems = $scope.displayItem.displayConfig[0].propertyValue;
console.info($scope.displayItem.displayConfig[0].propertyValue);
console.info($scope.displayItems);
});
}
break;
}
}
Short answer:
<ul data-ng-init="display(selecteditemslist,searchid)">
<li class="tag" ng-repeat="list in displayItems track by $index" ng-class="{selected: $index==selectedIndex}">
<span class="tag-label">{{list}}</span><span class="tag-cross pointer" ng-click="Delete($index,selecteditemslist[$index],list,searchid)">x</span>
</li>
</ul>
Long Answer:
Let’s see how the directive ng-repeat works.
First of all:
var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
var NG_REMOVED = '$$NG_REMOVED';
var ngRepeatMinErr = minErr('ngRepeat');
...
return {
restrict: 'A',
multiElement: true,
transclude: 'element',
priority: 1000,
terminal: true,
$$tlb: true,
compile: function ngRepeatCompile($element, $attr) {
var expression = $attr.ngRepeat;
...
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
var lhs = match[1];
var rhs = match[2]; <--- in this case `displayItems`
var aliasAs = match[3];
var trackByExp = match[4];
After that $scope.$watchCollection(rhs, function ngRepeatAction(collection) { ... }) is being made in ngRepeatLink.
As a result if displayItems is empty, we will get html comment: <!-- ngRepeat: list in displayItems --> instead of what you probably supposed to see: <div ng-repeat="list in displayItems" ng-init="display(selecteditemslist,searchid)">.
That’s why ng-init doesn’t initialize :)
Related
I have a nested ng-repeat with a filter to group by.
I have created this
fiddle.
var myApp = angular.module('myApp', []);
myApp.controller('myCtrl',['$scope', function($scope) {
$scope.data =[
{subject: 'English',module: 'Literature', score: 95},
{subject: 'Maths',module: 'Calculus', score: 90}
];
$scope.dropScore = function() {
if ($scope.data[0].score > 0) {
$scope.data[0].score -= 8;
}
}
$scope.origData = angular.copy($scope.data)
$scope.reset = function () {
$scope.data = angular.copy($scope.origData);
};
}])
.filter('groupBy', function() {
return _.memoize(function(items, field) {
return _.groupBy(items, field);
}
);
});
When you press the button hit score the score of English drops but clicking reset will reset the $scope.data value but not show the updated data on the screen.
Can someone help with this
Working Demo
Just use this reset method:
$scope.reset = function () {
$scope.data[0].score = angular.copy($scope.origData[0].score);
};
You need to call $scope.$apply() to refresh your scope :
$scope.dropScore = function() {
if ($scope.data[0].score > 0) {
$scope.data[0].score -= 8;
$scope.$apply();
}
}
http://jsfiddle.net/zewaeqpx/
When you do ng-repeat=(subject, value) in data | groupBy: 'subject', you are creating another array for ng-repeat to use. So either you would need to assign each parameter within or not use the filter in the ng-repeat.
Option 1:
If you want to keep how you are using the ng-repeat, you could to this:
$scope.reset = function () {
_.forEach($scope.data, function(subject, idx){
subject.score = $scope.origData[idx].score;
});
};
Option 2:
or you could simplify your ng-repeat so that it works like this where the template becomes:
<li ng-repeat="subject in data">
<span ng-bind="subject.subject"></span>
<ul>
<li ng-bind="subject.module + ' - ' + subject.score">
</li>
</ul>
</li>
You should use ng-bind because in some browsers, when the data attribute is not loaded, it will flash {{}} for a split second before it loads.
I want to display one symbol (🗸) when one or more of the values in a scope ($filter.producers) is set to true, and another one (X) when all the values are false. I am trying to do show with ng-show, but I cannot find the way to make it work.
My html goes like this:
<div ng-app="myApp" ng-controller="Ctrl">
{{ctrlTest}}
<span ng-show="filter.producers == false">X</span>
<span ng-show="filter.producers != false">🗸</span>
<hr/>
<div ng-repeat="elements in filter">
<div>
<li ng-repeat="(key,value) in filter.producers" ng-show="value">{{key}}
<a ng-click="filter.producers[key]=false"> X</a>
</li>
</div>
{{filter.producers}}
</div>
</div>
And my controller:
angular.module('myApp', [])
.controller('Ctrl', function($scope) {
$scope.ctrlTest = "Filters";
$scope.filter = {
"producers": {
"Ford": true,
"Honda": true,
"Ferrari": true
}
}
});
Here is a working plunker
Thanks in advance!
The value of filter.producers in your case, is this object: {"Ford": true, ..}. It certainly will not equals to true or false! If I get you question correctly, what you should do is plucking all it's value and check if any of these value is true or false, something like this:
//In your controller
$scope.anyProducerTrue = function() {
var anyTrue = false;
angular.forEach($scope.filter.producers, function(value, key) {
if (true == value) anyTrue = true;
});
return anyTrue;
}
//In your view
<span ng-show="!anyProducerTrue()">X</span>
<span ng-show="anyProducerTrue()">🗸</span>
you need another function to check all properties are true or false initially and when click (X) link to set false for a specific property and do not need two ng-repeat in your DOM. you can try my solution.
like:
your controller:
angular.module('myApp', [])
.controller('Ctrl', function($scope) {
$scope.ctrlTest = "Filters";
$scope.filter = {
"producers": {
"Ford": true,
"Honda": true,
"Ferrari": true
}
};
$scope.hideMe = function(key) {
$scope.filter.producers[key]=false;
$scope.checkAllproperty(); // call again to check all property
};
$scope.checkAllproperty = function() {
var allTrue = false;
for(var key in $scope.filter.producers) {
if($scope.filter.producers[key] === true){
allTrue = true;
}
}
$scope.allTrue = allTrue;
};
$scope.checkAllproperty(); // initial call when loaded
});
in html: call a hideMe function to set false
<div ng-app="myApp" ng-controller="Ctrl">
{{ctrlTest}}
<span ng-show="!allTrue">X</span>
<span ng-show="allTrue">🗸</span>
<p>
{{filter.brewers}}
</p>
<hr/>
<div>
<div>
<li ng-repeat="(key,value) in filter.producers" ng-show="value">{{key}}
<a ng-click="hideMe(key)"> X</a> // call to set this key false
</li>
</div>
{{filter.producers}}
</div>
</div>
use
Object.keys(filter.producers).length;
<span ng-show="Object.keys(filter.producers).length != 0">🗸</span>
JSBIN
you can use the JS Array.prototype.some function in your controller as follows:
$scope.flag = Object.keys($scope.filter.producers).some(
function(el) {
return $scope.filter.producers[el];
});
and in your HTML use the flag as follows:
<span ng-show="!flag">X</span>
<span ng-show="flag">🗸</span>
hello i'm trying to get element from the DOM in angular directive.
this element:
click image
i'm trying to get this element by unknow id this is the code:
pass user object:
<dashboard user="user" action="pageSelect(name,pageNumber)"></dashboard>
in templateUrl directive:
<section>
<li id="Dashboard{{$index}}" ng-repeat="dashboard in user.NavigationMenu">
<h3 class="PovDashboard">
<i class="fa fa-tachometer"></i>
{{dashboardName}}
</h3>
<ul class="povPages">
<li ng-repeat="page in dashboard.Pages"> <i class="povIconRight fa fa-angle-double-right"></i></li>
</ul>
</li>
and this is the problem:
scope.$watch('user', function(newValue) {
if (newValue !== undefined) {
console.log(scope.user.NavigationMenu[0].Pages);
var defaultDashboard = scope.user.DefaultDashboardID;
console.log(scope.user);
angular.forEach(scope.user.NavigationMenu,function(value,key){
if(value.ID === defaultDashboard){
console.log(key);
// i tried everything
var s = '#Dashboard' + key;
var e = angular.element.find(s)
//e is empty
console.log(e);
//i'm trying to do
//e.('.povPages').first().css("display","block");
}
})
}
});
thanks in advance
You are not using the jqLite wrapper angular.element() syntactically correct, i guess you should try with this:
angular.element(s).find('ul').css('display', 'block');
If you are not using jQuery then .find() will have a lookup at tagnames only.
From the docs:
find() - Limited to lookups by tag name
Or better do it with angular way with ng-show/ng-hide:
<ul class="povPages" data-ng-show='isVisible'>
initialize $scope.isVisible = false;now in the .$watch() do this:
scope.$watch('user', function(newValue) {
if (newValue != undefined) {
console.log(scope.user.NavigationMenu[0].Pages);
scope.isVisible = newValue != undefined ? true : false;
console.log(scope.user, scope.isVisible);
}
});
A sample demo:
angular.module('demoapp', []).controller('demoCtrl', ['$scope', '$timeout',
function($scope, $timeout) {
$scope.arr = [{
text: "one"
}, {
text: "two"
}];
$scope.isVisible = false;
$timeout(function() {
$scope.isVisible = true;
}, 2000);
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app='demoapp' ng-controller='demoCtrl'>
<div ng-repeat="obj in arr">
<h1>see if list is visible == {{isVisible}} {{obj.text}}</h1>
<ul ng-show='isVisible'>
<li>should be visible after value change. {{obj.text}}</li>
</ul>
</div>
</div>
I want to pass AngularJS Expression value to the controller.
HTML code :
<div data-ng-controller="AlbumCtrl">
<div data-ng-repeat="z in songInfo">
<div data-ng-repeat="b in z.album">
{{b.tracks}}
</div>
</div>
<!-- Pagination -->
<div class="pageing">
<a class="prev" data-ng-disabled="currentPage == 0" data-ng-click="currentPage=currentPage-1">prev</a>
<a class="pageingg" href="#/song">{{currentPage+1}}/{{numberOfPages()}}</a>
<a class="next" data-ng-disabled="currentPage >= data.length/pageSize - 1" data-ng-click="currentPage=currentPage+1">next</a>
</div>
</div>
Here {{b.tracks}} is the count of total number of tracks in the album. I have to pass this data to the controller AlbumCtrl.
Controller :
.controller('AlbumCtrl', function($scope, $routeParams, $http) {
$scope.album_id = $routeParams.albumId;
$http.post('api-call.php', { albumid: $scope.album_id, evt: 13 }).success(function(data) {
$scope.songInfo = data;
});
//Pagination
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.data = [];
$scope.numberOfPages=function(){
return Math.ceil($scope.data.length/$scope.pageSize);
};
for (var i=0; i<AngularJS expression value; i++) {
$scope.data.push("Item "+i);
}
});
Here, in controller AngularJS expression value is the value we have to get here.
if it have only one value. then you can easily get the values from controller, you don't need to pass it.
try this way $scope.songInfo[0].album[0].tracks
Something like
for (var i=0; i< $scope.songInfo[0].album[0].tracks; i++) {
$scope.data.push("Item "+i);
}
Try this two line,
var obj = JSON.parse($scope.songInfo);
var track = obj.root.tracks[0];
I'm struggling with angularjs directive templates. The {{variable}} works in a very strange way inside a ng-repeat,
<div ng-controller="MyCtrl">
<h2>here i am</h2>
<button type="button" ng-click="addItem()" class="btn btn-primary">Howdy</button>
<div ng-repeat="item in items track by $index" itemlist></div>
</div>
<script type="text/ng-template" id="template.html">
<div>
Howdy {{item.itemNum}} {{item.name}}
</div>
</script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function ($scope) {
$scope.count = 0;
$scope.items = [];
var newItem = {
itemNum: 0,
name: "New"
};
$scope.addItem = function () {
newItem.itemNum = $scope.count;
console.log('adding item ' + newItem.itemNum);
$scope.items.push(newItem);
$scope.count += 1;
};
});
myApp.directive('itemlist', function ($compile) {
return {
templateUrl: 'template.html',
};
});
I have created a jsfiddle showing my problem here: http://jsfiddle.net/dk253/8jm5tjvf/23/.
What am I missing or doing wrong?
Thanks!
The reason is you are updating the property on the same object reference (newItem) every time. So it updates all other items in the array because they all just point to the same object or in other words they are all same. You could instead get the copy of the object using angular.copy and push that item.
var item = {
itemNum: 0,
name: "New"
};
$scope.addItem = function () {
var newItem = angular.copy(item); //Get the copy
newItem.itemNum = $scope.count;
Fiddle