ng-repeat within ng-repeat in angular - javascript

I have a record that is returned from an angular $resource promise like below.
The record is an array and within each array of record there another variable array. I try displaying in my view like below.
div(ng-repeat="category in categories")
h6
img(src="{{category.ImageUrl}}")
|{{category.Name}}
ul(class="list-unstyled")
li(item in category.CategoryItems)
a(href="#") {{item.Item}} (0)
The problem is , category.CategoryItems returned undefined and empty as a result even though its actually an array of objects. Please how do i print those? Each category has category items of an array type. How do i best achieve this pls?

You didn't use ng-repeat the second time. Try this:
div(ng-repeat="category in categories")
h6
img(src="{{category.ImageUrl}}")
|{{category.Name}}
ul(class="list-unstyled")
li(ng-repeat="item in category.CategoryItems") //ng-repeat added
a(href="#") {{item.Item}} (0)

I used nested ng-repeat in my project some time ago. In my project the requirement was to show all blogs like in snapshot:
To achieve this you can use ng-repeat like in below code:
<div class="panel ">
<div class="panel-body">
<div class="col-sm-12 " ng-repeat="blogBlock in blogs" >
<h2 class="hot-topics-heading">{{blogBlock.year}}</h2>
<div class="blog-year>
<div class="col-sm-6" ng-repeat="months in blogBlock.data">
<span class="hot-topics-heading">{{months.monthName}}</span>
<div class="blog-month" >
<ul class="hot-topics-ul" >
<li class="blogTitle" ng-repeat="blog in months.data">
{{blog.title}}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
In the above code ng-repeat inside the ng-repeat and also inside the ng-repeat.
<div ng-repeat="blogBlock in blogs" >
<div ng-repeat="months in blogBlock.data">
<ul>
<li ng-repeat="blog in months.data"></li>
</ul>
</div>
</div>

Related

Plugin not applying changes on ngFor directed div Angular 5.2

I've been searching for the solution for a few days but unable to find one that works. The issue is that this div which has a class ish-container-inner, is linked to a js plugin which works only with this code below:
<div class="ish-container-inner ish-product">
<div class="ish-main-content ish-pflo-gal ish-scroll-anim ish-2col ish-square ish-content-parallax">
<div class="ish-item">
<div class="ish-item-container">
<div class="ish-caption-container">
<div class="ish-caption">
<span class="ish-h4 ish-txt-color9">Special Effects</span> <span class="ish-separator">/</span> <span>Ink</span></div>
</div>
<div class="ish-img">
<img src="assets/img/bniinks-003.jpg" alt="Project">
</div>
</div>
</div>
</div>
</div>
But as soon as I'll put *ngFor like below, it won't work. Even with ngIf present:
<div class="ish-container-inner ish-product" *ngIf="products">
<div class="ish-main-content ish-pflo-gal ish-scroll-anim ish-2col ish-square ish-content-parallax">
<div class="ish-item" *ngFor="let product of products">
<div class="ish-item-container">
<div class="ish-caption-container">
<div class="ish-caption">
<span class="ish-h4 ish-txt-color7">{{ product.name }}</span> <span class="ish-separator">/</span> <span>Ink</span>
</div>
</div>
<div class="ish-img">
<a href="product-detail.html" class="ish-img-scale" [style.background]="'url('+product.thumbnail+')'">
<img src="{{product.thumbnail}}" alt="Project"></a>
</div>
</div>
</div>
</div>
</div>
I have valid data at this point in products but the plugin is not working for these div elements. I don't know why. Without the ngFor directive. Div is assigned some stylings automatically which are changed by the plugin on scroll i.e.
<div class="ish-main-content ish-pflo-gal ish-scroll-anim ish-2col ish-square ish-content-parallax" style="position: relative; height: 629px; margin-top: -99.5455px;" data-initial-top="0">
But if I put ngIf or ngFor directive. It doesn't work anymore and these stylings are not assigned automatically. Awaiting response :)

Nested ng-repeat with constrained data

I have a nested ng-repeat as follows:
<div ng-repeat="item_l in list1">
<div ng-repeat="item_f in list2">
{{item_f}} {{item_l}}
</div>
</div>
It gives me about 20 results, but i want only 5 of them. How to do this?
You can use limitTo
<div ng-repeat="item_l in list1">
<div ng-repeat="item_f in list2 | limitTo : 5">
{{item_f}} {{item_l}}
</div>
</div>
DEMO APP

Angularjs ng-repeat and child elements

I'm attempting to insert a <br/> every nth element to achieve something like this (using ng-repeat and ng-if="!($index % 2)"):
<div class="container">
<div>
<span>1</span>
<span>2</span>
<br/>
<span>3</span>
</div>
</div>
I thought I could mimic how i've used ng-repeat in the past for <ul/> elements, as so:
<div class="container">
<ul ng-repeat="item in list">
<li>{{item}}</li>
</ul>
</div>
which produces a list such as this:
<div class="container">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
Yet when I attempt to do something like this:
<div class="container">
<div ng-repeat="item in list">
<span>{{item}}</span>
</div>
</div>
I get this differing result from the <ul/> usecase:
<div class="container">
<div>
<span>1</span>
</div>
<div>
<span>2</span>
</div>
<div>
<span>3</span>
</div>
</div>
The question is two-fold:
Why does the ng-repeat directive on a <ul/> behave differently
How can I have multiple span elements then a break without wrapping each span in a div?
https://docs.angularjs.org/api/ng/directive/ngRepeat
The ngRepeat directive instantiates a template once per item from a
collection. Each template instance gets its own scope, where the given
loop variable is set to the current collection item, and $index is set
to the item index or key.
In your loop, your 'item' has following local variables: $index, $first, $middle, $last, $even, $odd. Each except $index returns a boolean value that tells you if the item is, for example, $odd. Also take a look at the directive ngClassEven.
ng-repeat acts equal to any tag, maybe the presatantion of ul creates confusion,
look next example:
http://plnkr.co/edit/ig766DNNlQXihNS5ZGdY?p=preview
im separated:
<ul class="example-animate-container">
<li class="animate-repeat" ng-repeat="friend in friends">
and
<legeng>ul - ng repeat</legeng>
<ul class="example-animate-container" ng-repeat="friend in friends">
Try this.
<div ng-repeat="num in [1,2,3,4,5,6]">
<div>{{num}}</div>
<div ng-if="$index%2">whatever you want</div>
</div>
Result looks something like this.
1
2
whatever you want
3
4
whatever you want
5
6
whatever you want
Update:
If you want to insert a <br> every nth <span> then you can change your HTML to the following:
<div id="container">
<span ng-repeat="item in list">{{item}}
<br ng-if="$index % 2">
</span>
</div>
Tested in Firefox,Chrome,and Internet Explorer the results look like this:
12
34
56
All you have to do is remove the surrounding div elements and then change your html to the following(live preview: http://codepen.io/larryjoelane/pen/qbJXJm). The ng-repeat directive duplicates the number of child elements that are contained within the parent element. The <li> elements in your example do not contain any child elements. In other words <li> elements are child elements of the <ul> element by default. However <span> elements are not child elements of <div> elements by default. You will see similar behavior when you use ng-repeat for other elements like the <table> element and its <tr> and <td> tags.
HTML:
<div ng-app="app" ng-controller="spans">
<div id="container">
<span ng-repeat="item in list">{{item}}
</span>
</div>
</div>
Angular/JavaScript:
angular.module("app", []).controller("spans", ["$scope", function($scope) {
$scope.list = [1, 2, 3, 4, 5, 6];
}]);
And if you want each span to have a line break then apply the following CSS:
#container span {
display: block;
}

ng-repeat from within innerHTML function?

I have 3 columns. The first lists a list of subjects from an array. Within that array, each subject has it's particular courses listed within, and within that, the rest of the course information.
Can I have the ng-repeat "function" operate properly if it is placed using a .innerHTML function?
I could be using the wrong identifiers to try and call content from the array, which could also be causing my problems.
scope:
$scope.subjects = [
{text:'English', courses:[
{coursesub:'English 1', coursedata:[
{coursedesc:'test'}
]
}
]
},
{text:'Mathematics'},
{text:'Science'}
];
$scope.showDetail = function (todo) {
document.getElementById("courselistings").innerHTML = '<a ng-repeat="course in subject.courses" class="list-group-item" target="#courseinformation" ng-click="showDetail(course)">{{courses.coursesub}}</a>';
};
html + angularjs:
<div class="col-md-3" id="subjects">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Subjects</h3>
</div>
<div class="panel-body">
<div class="list-group">
<a ng-repeat="subject in subjects" class="list-group-item" target="#courselistings" ng-click="showDetail(subject)">
{{subject.text}}
</a>
</div>
</div>
</div>
</div>
<div class="col-md-3" id="courselisting">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Courses</h3>
</div>
<div class="panel-body">
<div class="list-group" id="courselistings">
test
</div>
</div>
</div>
</div>
<div class="col-md-6" id="courseinfo">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Course Info</h3>
</div>
<div class="panel-body">
<div class="list-group" id="courseinformation">
</div>
</div>
</div>
</div>
I haven't done the courseinfo panel stuff yet, I just included it so that the columns would align properly.
No, it won't work.
You need to use template or directive.
http://docs.angularjs.org/guide/directive
You simple move innerHTML string to directive template
.directive('myCustomer', function() {
return {
scope: {
subject: '='
},
template: '<string here>'
};
});
And use it like
<my-customer subject="xxx"/>
A directive is a better answer for you. DOM manipulation should be done in directives, not controllers.
That said, it is possible using Angular's $compile which makes Angular aware of new HTML.
Just as a proof of concept- here's that function (and a working fiddle):
$scope.showDetail = function (todo) {
var html= '<div><a ng-repeat="course in subjects['+todo+'].courses" class="list-group-item" target="#courseinformation" ng-click="showDetail(course)">{{course.coursesub}}</a></div>';
var innerHTML =$compile(html)($scope)
var currente = angular.element(document.getElementById("courselistings"));
currente.replaceWith(innerHTML);
}
In order for this to work we also need to pass in the index of the course you want to show -- ng-click="showDetail($index)". This is because the $compile will compile this against the controller scope, not the one inside the ngRepeat.
As you can see it takes jumping through a number of hoops to make this work- which is part of why a directive is better.

Angular JS Protractor extract data

using protractor I would like to extract some specific data from my Angular JS application.
The data I want to extract is embedded in a external div with id "jobHolder" inside this div I have several embedded divs each have an id "job_i". where i goes from 1 to n...
Here is the HTML :
<div class="thumbJobs" id="jobHolder" style=
"height: 275px; overflow: hidden;" tabindex="5052">
<div class="job ng-scope" id="job_1">
<div class="viewerEye" id="job_1_viewerEye"></div>
<div class="jobBigPicto transition_2_opa" id="job_1_jobBigPicto">
<div class="jobsSmallPictos transition_2_opa" id=
"job_1_jobsSmallPictos">
<div class="jobDown transition_2_opa" id="job_1_jobDown">
<div class="jobTitle ng-binding">
TSK(Z87700J)(000)(Z87700JU00)(000)
</div>
<div class="jobText ng-binding"></div>
</div>
<div class="jobHoverInfo" id="job_1_jobHoverInfo"></div>
<div class="job ng-scope" id="job_2">
<div class="job ng-scope" id="job_3">
<div class="job ng-scope" id="job_4">
<div class="job ng-scope" id="job_5">
<div class="job ng-scope" id="job_6">
<div class="job ng-scope" id="job_7">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
What I would like to extract is the jobTitle in each inernal DIV. I have tried with repeaters but i could not extract all data so I am trying to use Id instead.
I want to extract all data ambedded in a div having id = job_i where i goes from 1 to the last index of the last DIV with the same id?
I have used this code to extract the data but the code Displays only the first 6 elements.
Could it be a synchronisation ot time out issue?
for (var i=1; i<20;i++)
{
var result = ptor.findElement(by.xpath('html/body/div[2]/div[1]/section[5]/div[4]/div['+i+']/div[4]/div[1]'));
result.getText().then(function(text)
{
console.log(text);
});
And here is the console output it shows only 6 elements whereas the web page is displaying 20 elements :
TSK(Z87700J)(000)(Z87700JU00)(000)
TSK(AGD170JFZZ)(000)
TSK(ZA1112O)(000)(ZA1111OU00)(000)
TSK(ZA1100O)(000)(ZA1100OU00)(000)
TSK(ZA1111O)(000)(ZA1111OU00)(000)
WAR27_STEP16 A TASK FOR CHAR FR
AN TASK WITH SPACE
WAR81_STEP_NETWORK_SESSION_MU
TSK(TTS758J)(000)(TTS758JN00)(000)
.
Finished in 10.851 seconds
1 test, 0 assertions, 0 failures
You may be hitting a timing issue since by default all findElement requests are asynchronous in nature and return a Promise. You might be better off writing your code as follows:
for (var i=1; i<20;i++)
{
ptor.findElement(by.xpath('html/body/div[2]/div[1]/section[5]/div[4]/div['+i+']/div[4]/div[1]'))
.then(function(result){
result.getText().then(function(text)
{
console.log(text);
});
});
This should wrap each one of the findElement requests so that they each get handled properly after the promise resolves.
Another thing you might look at is using findElements to get back an array that you then iterate and dump to the console.
Hope this helps.

Categories

Resources