ng-repeat inside document with specific ID - angularjs

I've a document with array inside eg.:
$scope.items = [
{
"id": 1,
"name": "Apple"
"types": [{
"color": "red"
"size": "xxl
},
{
"color: "green"
"size": "S"
}]
},
{
...
}]
And i'd like to display all records from Array "types" only for items ID = 1.
I tried this (doesn't work):
table(style="width:100%")
tr(ng-repeat="type in items.types" ng-if="items.id==1")
td
p {{ type.color}}
td
p {{ type.size}}

This can be easily implement by having two ng-repeat with filter, which will filter out the items which has id 1, and do ng-repeat on that types collection.
table(style="width:100%")
tbody(ng-repeat="item in items | filter: {id: 1 }: true")
tr(ng-repeat="type in items.types")
td
p {{ type.color}}
td
p {{ type.size}}

Related

Using ng-if and ng-repeat correctly

I have a rudimentary understanding of AngularJS and have a couple (possibly stupid) questions about ng-if and ng-repeat.
If I have a ng-repeat that looks like this:
For all containers without titles, would the ng-repeat produce those containers and not show them? Or do they simply don't exist? The reason I ask is I've tried to replace ng-if with ng-show, but it does not produce the same outcome of "hiding" containers that do not have titles.
Is there a way to code a ng-if to say if the next container has no title, then do something. I tried something like ng-if="item.title=='' && $index+1", without any luck.
Any suggestions?
My data looks like this:
"_sections": [{
"_bootstrap_cells": 6,
"_count": 2,
"visible": true,
"columns": [{
"fields": [{
"name": "type_of_account",
"type": "field"
}, {
"name": "routing_transit_number",
"type": "field"
}]
}, {
"fields": [{
"name": "type_of_payment",
"type": "field"
}, {
"name": "check_digit",
"type": "field"
}]
}],
"caption": "Direct Deposit",
"id": "b456b9d2137ac340177c36328144b0ef"
}, {
"_bootstrap_cells": 12,
"_count": 1,
"visible": true,
"columns": [{
"fields": [{
"name": "account_number",
"type": "field"
}, {
"name": "account_title",
"type": "field"
}, {
"name": "financial_institution_name",
"type": "field"
}]
}],
"caption": "",
"id": ""
}
}]
The first section has two columns and a bootstrap cell value of 6 for each column, the second section only has one column and a bootstrap cell of 12. Since the second doesn't have a caption, I want it to be appended to the first section, but keep both sections' bootstrap formatting.
If containers is an array then it does not have a title property. You need to check the title on each item.
Also note that ng-if will not hide the content, but remove it or not insert it into the DOM. The counterpart of ng-show is ng-hide.
angular.module('appModule', [])
.controller('MyController', [function() {
this.containers = [{
aaa: 1,
title: 'One'
}, {
aaa: 2,
title: ''
}, {
aaa: 3,
title: 'Three'
}]
}]);
angular.bootstrap(window.document, ['appModule'], {
strictDi: true
});
<div ng-controller="MyController as myCtrl">
<div ng-repeat="item in myCtrl.containers track by $index">
<div ng-if="item.title!=''">{{$index}}. {{item.title}}</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>

angularjs ng-repeat filter based on array length

I was wondering, how do I put a filter a ng-repeat that will only bring back items that have colours? I was hoping to have a checkbox above the grid entitled "Show ones with colours" that would filter the list based on the count of the colours array when it was selected, and display ALL when unselected.
{
"_id": "54d13c3f3c25d5d8123a1d62",
"name": "Barry",
"colours": ["239, 101, 128"]
},
{
"_id": "54d13sfg5d5d8hgf6gg",
"name": "John",
"colours": []
},
{
"_id": "34d13sfg5d5d4tt6g",
"name": "Andrew",
"colours": []
},
{
"_id": "44d165d5d4t77t6g",
"name": "Gary",
"colours": ["25, 234, 22", "5, 100, 255"]
},
The following would give everyone not having colours:
<div ng-repeat="item in items | filter: { colours: '!' }">
Negate it again and you get everyone having colours:
<div ng-repeat="item in items | filter: { colours: '!!' }">
Demo: http://plnkr.co/edit/oIl3ohe0TLMWcQlTPuY5?p=preview
I think you an use a controller function to test for the presence of colours
so in haml/coffeescript
%tr{"ng-repeat2 => "item in list | filter: hasColour(item)"}
and hasColour is a controller function
$scope.hasColour= (item) ->
item.colours.length > 0
Untested I'm afraid

How do I hide the square brackets in my template expressions?

I have a simple JSON object in my models
whitelist = [
{
"name": "Whitelist #1",
"permissions": [
"production_sdk",
"source_sdk",
"service"
],
},
{
"name": "Whitelist #2",
"permissions": [
"production_sdk",
"service"
],
},
{
"name": "Whitelist #3",
"permissions": [
"production_sdk",
"source_sdk"
],
}
]
In my html I have {{ whitelist.permissions }}, but the HTML displays the values with brackets - ['production_sdk', 'source_sdk'].
How can I display the HTML so that there are no brackets?
whitelist.permissions is an array, how do you want that to be displayed in your html? You should probably create a simple filter that takes an array and outputs what you want, but you could just change your html to do this to get a comma-separated list:
{{ whitelist.permissions.join(', ') }}
Another option, especially if you want to style each permission, is to use ng-repeat and html elements:
<span ng-repeat="permission in whitelist.permissions"><span ng-if="$index != 0">, </span>{{ permission }}</span>

AngularJS push to array parse in view

I have a controller where I declare the model like this:
$scope.Model =[];
after I make a rest call and the result I push it to the model:
$scope.Model.push(results.data);
The data returned can be in different length and size:
Name
Email
Items
Item 1
Item 2
Item n
Roles
Role 1
Role 2
Role n
What is the best practice of handling this with arrays in AngularJS and using ng-repeat in view in order to show the data?
Should I declare my array like this:
$scope.Model =[];
and push the results:
$scope.Model.push(results.data);
or like this:
$scope.Model =[{
Name: '',
Email: '',
Items: [{
Id: '',
Name: '',
Price: ''
}],
Roles: [{
Id: '',
Name: ''
}],
}];
and asign the results:
$scope.Model = results.data;
It is based on your response and scenarios. but ng-repeat expects Array or Array list.
1) Array
Example 1 (plain array response)
$scope.names= ["Apple", "Banana", "Orange"];
<ul>
<li ng-repeat="x in names">
{{ x }}
</li>
</ul>
Example 2 (Object response that has array)
$scope.names= {
"fruits": ["Apple", "Banana", "Orange"]
};
<ul>
<li ng-repeat="x in names.fruits">
{{ x }}
</li>
</ul>
2) Array List
Example 1 (plain array list response)
$scope.names = [{
"id": "1",
"name": "Asik"
},
{
"id": "1",
"name": "John"
},
{
"id": "1",
"name": "Smith"
}];
<ul>
<li ng-repeat="x in names">
id:{{ x.id }}, name:{{ x.name }}
</li>
</ul>
Example 2 (Object response that has array list)
$scope.names = {
"success": "true",
"items": [{
"id": "1",
"name": "Asik"
},
{
"id": "1",
"name": "John"
},
{
"id": "1",
"name": "Smith"
}]
};
<ul>
<li ng-repeat="x in names.items">
id:{{ x.id }}, name:{{ x.name }}
</li>
</ul>
Basically, service/ajax response comes as Array or Array list. So you don't need to do the following steps.
$scope.Model =[];
$scope.Model.push(results.data);
But the above case comes in some situation (for eg: merging 2 service/ajax responses )
I have used the following:
angular.copy(results.data, $scope.Model)
This will actually copy the results from the rest servicve into my model without having to declare each property of the model.

ng-repeat does not react to given limitTo or filter

I have a directive that displays subcategories of a feature list.
Problem is, all items are displayed, regardles of the filters i use for the ng-repeat.
I use a filter to only show items with a certain category_uid and i also use a limitTo.
app.directive('featureCategory', function() {
return {
restrict: 'A',
transclude: true,
link: function($scope) {
$scope.featureCountBuffer = $scope.featureCount;
$scope.listLength = Object.keys($scope.featureList).length;
},
scope: {
featureList: '=',
featureCount: '#',
categoryId: '#'
},
template:
'<li>featureCountBuffer : {{featureCountBuffer}} / listLength {{listLength}} / categoryId {{categoryId}}</li>' +
'<check-item ng-repeat="feature in featureList | filter:{category_uid:categoryId} | limitTo: featureCountBuffer" feature="feature"></check-item>'
}
});
This shows above 40 items thou it starts with the li element showing featureCountBuffer is 5 andcategory_uid being 1 which only applies to 8 items.
Does anyone see my Mistake here?
The featureList looks like this:
{
"1": {
"uid": "1",
"title": "foo",
"category_uid": "1",
"checked": false
},
"2": {
"uid": "2",
"title": "bar",
"category_uid": "1",
"checked": false
},
"3": {
"uid": "3",
"title": "foobar",
"category_uid": "2",
"checked": false
},
"4": {
"uid": "4",
"title": "barfoo",
"category_uid": "2",
"checked": false
},
"5": {
"uid": "5",
"title": "barbar",
"category_uid": "3",
"checked": false
}
...
}
I found the Problem.
Angulars ng-repeat works with objects of objects but the filters do not.
You can either write your own filters to fix this or just use an array of objects.
I used lodash's _.toArray to convert mine. My Changes:
[..]
link: function($scope) {
[..]
$scope.featureList = _.toArray($scope.featureList);
},
[..]
Youcan read about it in more detail in this article.
Thanks for posting this! I found an alternative solution to use the $index property:
<ul>
<li ng-repeat="(id, value) in test" ng-if="$index < 3" >
{{ $index }} {{ id }} {{ value }}
</li>
</ul>

Resources