AngularJS - ng-repeat is not working for inner properties - angularjs

Here is an object that I'd like to use with ng-repeat, but it's not able to see the inner firstlang property:
$scope.school{
name : "stackoverflow",
sub :{
firstlang : "kannada"
}
}
Here is my ng-repeat:
<ul>
<li ng-repeat="index in school.sub">
first language is = {{index.firstlang}}
</li>
</ul>
The desired result is: first language is = kannada

Looking at your example it is not very clear how the school.sub data structure should look like in the end... Is it supposed to be an object (as in the example data structure) or an array (as you ngRepeat seems to suggest).
Provided that the school.sub is an object this would work: http://jsfiddle.net/pkozlowski_opensource/WXsFD/1/
<li ng-repeat="(key, value) in school.sub">first language is = {{value}}</li>
On the other hand, if you plan your sub structure to be an array the proper approach would be:
http://jsfiddle.net/pkozlowski_opensource/WXsFD/2/
<li ng-repeat="index in school.sub">first language is = {{index.firstlang}}</li>
Hope that the above jsFiddles clarify how to approach both situations.

Related

Angularjs: Ng-repeat and unique filter in array

I have a set of data like this
$scope.students = [
{ name:"John", courses:["Math", "Physics", "Chemistry"] },
{ name:"Paul", courses:["Economics", "Math", "Sociology"] }
]
I would like a way to filter using angular-filter so that I can get a list of all the subjects without repetition.
I've been trying to use unique filter, but I cannot get it to work since I try to iterate like
<ul ng-repeat="student in students">
<li ng-repeat="x in student.courses | unique:courses"></li>
{{x}}
</ul>
My desired output of the first ng-repeat would be an array like this:
["Math", "Physics", "Chemistry", "Economics", "Sociology"]
so I could iterate through it in the second one.
I have achieved this throught making a new scope with just the desired array, but then I cannot bind it properly, so I would like to achieve it through filtering. Thanks in advance.
I would really recommend you using the libraries Lodash or Underscore for this kind of problems. Learning to master these has helped me a lot!
Of course, you can create your own angular filter using one of them. The method you would like to use is union:
_.union(_.flatten(_($scope.students).pluck("courses")))
I use pluck to get out the courses arrays from the studens object, then I flatten the result (to get rid of the array that it comes nested in), and then i use union to get each subject only once.
If the requirement actually is to:
...get a list of all the subjects without repetition.
Then I would make a separate array for subjects:
$scope.courses = [];
// There are many ways to do skin this cat... (prograde does have a point!)
$scope.students.forEach(function(student) {
student.courses.forEach(function(course) {
if ( $scope.courses.indexOf(course) === -1 ) {
$scope.courses.push(course);
}
})
});
HTML
<ul>
<li ng-repeat="course in courses">
{{ course }}
</li>
</ul>
And if the students change I would recreate the courses-array.
But it sounds as if you are trying to do something else.
But it doesn't give the desired output.
It would help if you tell us what that desired output is!
http://plnkr.co/edit/bZNjIEFznvuyTU3zxAp1?p=preview

Is there any directive that acts like a "with" in angular?

Say you have an object yourObject on the scope and you want to access some deep properties like the following :
<ol>
<li ng-bind="yourObject.thing.map.one"></li>
<li ng-bind="yourObject.thing.map.two"></li>
<li ng-bind="yourObject.thing.map.three"></li>
</ol>
Is there any built-in directive that could make it look more like this:
<ol ng-with="yourObject.thing.map">
<li ng-bind="one"></li>
<li ng-bind="two"></li>
<li ng-bind="three"></li>
</ol>
UPDATE
A similar question was already. Please see Equivalent of {{#with}} in angular
One way I would do this scenario is by implementing a controller that will have a variables to those an array of one, two three... and then using ng-repeat to loop over that.
So for ng-controller, you could write, ng-controller="SomeCtrl as ctrl"
and then ctrl.arrayVariable would hold an array of all the data you want to show
To make matters very simple, you could use ng-repeat to loop through the data.
So, possibly, ng-repeat="var in ctrl.arrayVariable"
Anyways, I'm not sure exactly how your code is structured, but it should work in most instances.
Long story short, ng-repeat is awesome

Filtering an Angular 1.2 ng-repeat with "track by" by a boolean property

I'm trying to filter some list items based on the value of a boolean property, but no matter what I do the entire list is always displayed. A few of the the things I've tried have been so broken that nothing displays, but that's neither here nor there. I can't get my filtering working as desired:
$scope.attendees = [
{"firstname":"Steve", "lastname":"Jobs", "arrived":true, "id":1}
,{"firstname":"Michelle", "lastname":"Jobs", "arrived":false, "id":2}
,{"firstname":"Adam", "lastname":"Smith", "arrived":true, "id":3}
,{"firstname":"Megan", "lastname":"Smith", "arrived":false, "id":4}
,{"firstname":"Dylan", "lastname":"Smith", "arrived":false, "id":5}
,{"firstname":"Ethan", "lastname":"Smith", "arrived":false, "id":6}
];
Using the following ng-repeat filtering:
<ul>
<li ng-repeat="person in attendees track by person.id | filter:arrived:'false'">
{{person.lastname}}, {{person.firstname}}
</li>
</ul>
I feel like I've tried every permutation that I can find referenced, most of which came from various StackOverflow search results:
filter:'arrived'
filter:arrived
filter:'person.arrived'
filter:person.arrived
filter:{arrived:true}
filter:{arrived:'true'}
filter:{person.arrived:true}
filter:{person.arrived:'true'}
I've also tried creating a custom filter function:
$scope.isArrived = function(item) {
return item.arrived;
};
And applying it thusly:
filter:isArrived
filter:'isArrived'
filter:{isArrived(person)}
filter:isArrived(person)
filter:'isArrived(person)'
None of these seems to work. What am I missing?
Here's a plnkr that demonstrates my problem.
The track by needs to be at the end of the expression:
<li ng-repeat="person in attendees | filter: {arrived: false } track by person.id">
#Gruff's answer is right, but just to give an answer from an official source:
From the Angular ng-repeat docs:
Note: track by must always be the last expression:
<div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
{{model.name}}
</div>
It also appear on the "Arguments" part of the docs:
Note that the tracking expression must come last, after any filters,
and the alias expression.

AngularJS not able to include markup in IDs?

I have an array of 3 items and want them to be "ng-repeated"
<li ng-repeat="item in obj.items id="testobj{{testobj.number}}">
</li>
When I look at the page, it appears that the id of the "li" is just "testobj" for all 3 items and not testobj1 testobj2 testobj3 like I was expecting. What is the issue?
Your ng-repeat attribute is missing a final ".
The {{ }} binding is probably coming back with no data and so being treated as if it was an empty string. I see no reference to testobj (the scope variable) anywhere outside of your binding. Is this defined, or should your id read id="testobj{{item.number}}" or something similar?

AngularJS filter with multiple perms

i have a users like this
[{id:1,name:'name',parent_id:0,type:1},
{id:2,name:'name2',parent_id:0,type:2},
{id:3,name:"name1 child",parent_id:1,type:1}]
and i am trying to display parents and child users based on parent_id and type id so for example id 3 is child of id 1 and i am trying to display them like this
http://jsfiddle.net/U3pVM/689/
thanks for help
I fixed up your fiddle:
http://jsfiddle.net/eQP8S/
<div ng-controller="MyCtrl">
<ol>
<li ng-repeat="user in users | filter:{parent_id:0}">
{{user.name}}
<ol>
<li ng-repeat="child in users | filter:{parent_id:user.id, type:user.type}">
{{child.name}}
</li>
</ol>
</li>
</ol>
</div>
Your main problem was that you were trying to use the "filter" filter with a function, which is okay, but that function isn't allowed to take any parameters. If you actually need to create a filter that takes parameters you have to write a custom filter: http://docs.angularjs.org/guide/dev_guide.templates.filters.creating_filters.
But in your case, you can use the standard "filter" filter and pass it objects that will do what you want.
Also, curse you Angular developers for creating an abstraction called filter and then creating a "filter" filter. I mean, how confusing is that?
That is not the correct way to use filters. If you check the documentation, you have three options:
use a string. It will be searched deeply in the object. Any object with some deep value containing the string will match
use a function. It will be called for elements of the array. You should provide any parameter in the function's scope, not as a parameter to the filter.
use an object. It will work like the string match, but for specific properties.
If you use the third case
<li ng-repeat="child in users | filter:{parent_id: user.id, type: user.type}">
and moreover print the child's name
{{ child.name }}
then you'll see the correct results.
http://jsfiddle.net/waAc7/

Resources