AngularJS- Items within ng-repeat not updating on variable update - javascript

I have an array called altSegments, and based on $scope.firstSeg or $scope.lastSeg I'd like to display different parts of that same array. In most cases I change the altSegments array alltogether and it updates fine, but when I go from the same altSegments array to the same array but change the $scope.firstSeg and $scope.lastSeg it doesn't update properly.
I suspect it has something to do with altSegments not having changed and therefore AngularJS deciding that it's not worth it to go over the code again and re-display. How would I get around this?
<li ng-repeat="altseg in altSegments">
<!-- For multiflight home to first -->
<div ng-show="{{firstSeg}}" ng-repeat="flights in altseg.segment_details_1.leg_details">
<p class="small dark">
<strong>Flight:</strong> {{flights.Carrier}} {{ flights.FlightNumber}}
</p>
<p class="small dark">
<strong>Departure:</strong> {{flights.OriginName}} | {{flights.DepartureTime | splitDT }}
</p>
<p class="small dark">
<strong>Arrival:</strong> {{flights.DestinationName}} | {{flights.ArrivalTime | splitDT }}
</p>
</div>
<!-- For multiflight last to home -->
<div ng-show="{{lastSeg}}" ng-repeat="flights in altseg.segment_details_2.leg_details">
<p class="small dark">
<strong>Flight:</strong> {{flights.Carrier}} {{ flights.FlightNumber}}
</p>
<p class="small dark">
<strong>Departure:</strong> {{flights.OriginName}} | {{flights.DepartureTime | splitDT }}
</p>
<p class="small dark">
<strong>Arrival:</strong> {{flights.DestinationName}} | {{flights.ArrivalTime | splitDT }}
</p>
</div>

ng-show is an angular directive and evaluates angular code;
Therefore; you do not need : ng-show="{{firstSeg}}"
Remplace with : ng-show="firstSeg"
See full documentation of ng-show here: https://docs.angularjs.org/api/ng/directive/ngShow

it looks like you are using ng-show="{{firstSeg}}" this should be ng-show="firstSeg" ..
If still doesn't work,
Try to update the data from controller side in $scope.apply() ...
e.g :-
$scope.apply(function(){
list = updated_list; // put your updation of list here
});

Related

Is it possible to assign the hash(#) automatically in angular?

Is there any way where I can assign the hash(#) automatically to the elements inside an ngfor?
<div *ngFor="let note of notes; index as i">
<h3 #[note][i]>
{{ note }}
</h3>
</div>
The result I would expect would be something like this:
<div>
<h3 #note11>
note1
</h3>
</div>
<div>
<h3 #note122>
note12
</h3>
</div>
<div>
<h3 #note153>
note15
</h3>
</div>
You can use the index variable to automatically assign a unique id to each element in the ngFor loop. Here's an example:
<div *ngFor="let note of notes; index as i">
<h3 id="note{{i}}">
{{ note }}
</h3>
</div>
This will give each element an id of "note0", "note1", "note2", etc.
Regarding using #, it is not possible to use it in such a way. The # symbol is used to create a template reference variable, you can use it like <h3 #myNote>{{ note }} and you can access the element using myNote in your component.
Try this:
<div *ngFor="let note of notes; index as i">
<h3 #{{note}}{{i}}>
{{ note }}
</h3>
</div>
Note:
This would do your work but # is used to create template reference.

angular repeat with template?

I'm currently trying to figure out how to use templates in angular. At present, I'm playing with ui.router (angular-ui-router) but I can't find good documentation on how the templating language is used to embed a sub-template view, especially as relates to a repeating element for different model instances.
BACKGROUND:
I am basically converting a static-local-filesystem image uploader/manager to work with amazon S3. The background essentials are already worked out, now I'm trying to improve the UI itself by converting it from 10 year old javascript to angular.js. I have it 'working' for an all-in-one html page but would prefer to modularize it to make it more dynamic.
CONTEXT:
I get a list of objects under a given prefix back from a listObjectsV2() call to the AWS sdk via the s3 client. I parse the results to break it into a pseudo-directory tree then display one directory at a time starting at the [virtual] root dir just after the prefix. (FYI the prefix is a userid)
I built a UserDir object that uses a PseudoDir sub object to define a virtual directory with array properties for 'subdirs' (more PseudoDir objects representing virtual sub-directories) and 'images' (S3 objects that are image files of one type or another).
What I want to display for any given 'current' directory (e.g. "" or the user root) is first a list of folder icons for each the curDir.subdirs, then a thumbnail icon for each of the curDir.images.
QUESTION:
I already have this working from a single html file and even managed to figured out how to use ui.router to create a for the main page. Now I want to modularize it so that a different controller will handle folder icon/info behavior, and another for image icons/behaviors.
i.e. I have already started building a 'FolderController' and a 'ImageController' and would like the ngRepeat for 'image in curDir.images' for example, to invoke a state with it's own template but I can't seem to find an example on how to do that.
Here is the current all-in-one template code. But I would like to move each sub-block into a state for FolderController with a templates/folder.html template and one for ImageController with a templates/image.html but can't seem to find an example of how to write the syntax:
<!-- folders -->
<div ng-repeat="(folder, pDir) in subdirs" ng-controller="FolderController" ng-init="folderName=folder;awsObject=pDir">
<div id="{{folderName}}" class="Item">
<div class="Icon ui-draggable ui-draggable-handle">
<img id="{{folderName}}Icon" src="../../images/folder.png">
</div>
<div id="{{folderName}}Desc" class="Description">
<span id="{{folderName}}Name" class="filename" title="{{folderName}}/">{{folderName}}/</span>
</div>
</div>
</div>
<!-- images -->
<div ng-repeat="(filename, uImage) in images" ng-controller="ImageController" ng-init="uImage=uImage">
<div id="image{{uImage.hash}}" class="Item">
<div class="Icon ui-draggable ui-draggable-handle">
<img id="icon{{uImage.hash}}" ng-src="{{ uImage.thumbSrc }}"></div>
<div id="desc{{uImage.hash}}" class="Description">
<span id="name{{uImage.hash}}" class="filename" title="{{filename}}">{{filename}}</span>
<img id="thumb{{uImage.hash}}" src="../../images/tick_image-services.png" class="Check Right" ng-show="uImage.usedInLayout" title="Used in layout"><br />
<span id="date{{uImage.hash}}" ng-show="(uImage.mtime > 0)">Date uploaded: {{ uImage.mtime | date: 'EEE MMM dd yyyy' }}</span><br />
<span id="size{{uImage.hash}}" ng-show="(uImage.size > 0)">Size: {{ uImage.size | humanizeBytes }}</span><br />
<span id="dims{{uImage.hash}}" ng-show="((uImage.width > 0) && (uImage.height > 0))">Dimensions: {{ uImage.width }} x {{ uImage.height }} pixels</span><br />
<span id="aspect{{uImage.hash}}" ng-show="(uImage.aspectRatio)">Aspect Ratio: <span class="AspectRatio">{{ uImage.aspectRatio }}</span></span><br />
</div>
</div>
</div>
You can create two components, one for folders and one for images, see here for official docs.
A rough draft would look like:
angular.module('myApp').component('images', {
templateUrl: 'imageList.html',
bindings: {
images: '='
}
});
imageList.html:
<div ng-repeat="(filename, uImage) in images" ng-controller="ImageController" ng-init="uImage=uImage">
<div id="image{{uImage.hash}}" class="Item">
<div class="Icon ui-draggable ui-draggable-handle">
<img id="icon{{uImage.hash}}" ng-src="{{ uImage.thumbSrc }}"></div>
<div id="desc{{uImage.hash}}" class="Description">
<span id="name{{uImage.hash}}" class="filename" title="{{filename}}">{{filename}}</span>
<img id="thumb{{uImage.hash}}" src="../../images/tick_image-services.png" class="Check Right" ng-show="uImage.usedInLayout" title="Used in layout"><br />
<span id="date{{uImage.hash}}" ng-show="(uImage.mtime > 0)">Date uploaded: {{ uImage.mtime | date: 'EEE MMM dd yyyy' }}</span><br />
<span id="size{{uImage.hash}}" ng-show="(uImage.size > 0)">Size: {{ uImage.size | humanizeBytes }}</span><br />
<span id="dims{{uImage.hash}}" ng-show="((uImage.width > 0) && (uImage.height > 0))">Dimensions: {{ uImage.width }} x {{ uImage.height }} pixels</span><br />
<span id="aspect{{uImage.hash}}" ng-show="(uImage.aspectRatio)">Aspect Ratio: <span class="AspectRatio">{{ uImage.aspectRatio }}</span></span><br />
</div>
</div>
and your original html would look like:
<!-- folders -->
<div ng-repeat="(folder, pDir) in subdirs" ng-controller="FolderController" ng-init="folderName=folder;awsObject=pDir">
<div id="{{folderName}}" class="Item">
<div class="Icon ui-draggable ui-draggable-handle">
<img id="{{folderName}}Icon" src="../../images/folder.png">
</div>
<div id="{{folderName}}Desc" class="Description">
<span id="{{folderName}}Name" class="filename" title="{{folderName}}/">{{folderName}}/</span>
</div>
</div>
</div>
<image-list [images]="images" ></image-list>
EDIT
Here is an example plunker which shows a simple implementation of a component, with data binding and ng-repeat in it, no need for ui-router for what you asked for. Please note that the html I wrote above is a botched copy paste of what you wrote - so the double ng-repeat was a mistake, updated the html.

How to loop through unknow number of nested json object in Angular with ngFor?

I'm trying to display all the reply from this json :
https://www.reddit.com/r/AskReddit/comments/k8w43d/people_with_the_last_name_pepper_who_have.json
So, depending of the post im loading and the reply, my number of children will differ. How can I loop throught it until I reach the last reply with children (body[2].data.children) ?
Like this :
<div class="replies-box" *ngFor="let reply of comments.body[1].data.children">
<div class="reply-header">
<p class="reply-author"><b>From</b> : {{ reply.data.author }}</p>
<p class="reply-send"><b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</div>
I have only the first level of reply, is there a way to simply loop through them all ?
Thanks in advance.
I would use a recursion type of approach.
Develop a app-comment component and if comment has children, loop over the children and display the app-comment. That way it will loop over the comments until no more children
<div *ngIf='comment'>
<span *ngIf='comment.kind; else showComment'>Kind: {{ comment.kind }}</span>
<ng-template #showComment>
<span>{{ comment }}</span>
</ng-template>
<div>
<app-comment *ngFor='let child of comment.data?.children' [comment]='child'> </app-comment>
</div>
</div>
See this sample illustration
Simply use ngFor inside ngFor with help of ng-container (will not create extra dom elements)
<div class="replies-box">
<ng-container *ngFor="let commentBody of comments.body">
<ng-container *ngFor="let reply of commentBody.data.children">
<div class="reply-header">
<p class="reply-author">
<b>From</b> : {{ reply.data.author }}
</p>
<p class="reply-send">
<b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}
</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</ng-container>
</ng-container>
</div>

How an i change the pagination-control numbers(1 2 3) to other values like 'Anything1 Anything2 ...' using ngFor* on array in ngx-pagination?

Is it possible to replace ngx-pagination's 'pagination-control'? By defaults, page numbers are showing like '1 2 3'. And I want to replace them with a string value in the array.
<pagination-controls (pageChange)="pageChange($event)" class="my-pagination"></pagination-controls>
The above code will display pagination numbers like
I want to replace the number with values from an array [Anything1, Anything2, Anything3].
Here my data is fixed and I know my page number count and its details.
You need to have look at custom template of ngx-pagination. In customization part you may try to add your Anything before {{page.label}}.
Custom Template example can be found here. http://michaelbromley.github.io/ngx-pagination/#/custom-template
<pagination-template #p="paginationApi"
[id]="config.id"
(pageChange)="config.currentPage = $event">
<div class="custom-pagination">
<div class="pagination-previous" [class.disabled]="p.isFirstPage()">
<a *ngIf="!p.isFirstPage()" (click)="p.previous()"> < </a>
</div>
<div *ngFor="let page of p.pages" [class.current]="p.getCurrent() === page.value">
<a (click)="p.setCurrent(page.value)" *ngIf="p.getCurrent() !== page.value">
<span>Anything{{ page.label }}</span>
</a>
<div *ngIf="p.getCurrent() === page.value">
<span>Anything{{ page.label }}</span>
</div>
</div>
<div class="pagination-next" [class.disabled]="p.isLastPage()">
<a *ngIf="!p.isLastPage()" (click)="p.next()"> > </a>
</div>
</div>
</pagination-template>

not able to print values of object using ng-repeat

This is my html code :
<h3 ng-repeat="goal in goals" ng-controller="AddGoalsCtrl">
<h4 ng-repeat="(key,value) in goal" ng-controller="AddGoalsCtrl">
{{key}} : {{value}}
</h4>
</h3>
and this is what my service layer returns :
[Goal [goalId=1, goalName=goal1, goalDescription=goaldescript, measurementCriteria=crtr, visible=Y], Goal [goalId=2, goalName=goal1, goalDescription=goal 1 description, measurementCriteria=criteria1, visible=Y], Goal [goalId=3, goalName=goal1, goalDescription=goal 1 description, measurementCriteria=criteria1, visible=Y]]
or json as :
[{"goalId":1,"goalName":"goal1","goalDescription":"goaldescript","measurementCriteria":"crtr","visible":"Y"},{"goalId":2,"goalName":"goal1","goalDescription":"goal 1 description","measurementCriteria":"criteria1","visible":"Y"},{"goalId":3,"goalName":"goal1","goalDescription":"goal 1 description","measurementCriteria":"criteria1","visible":"Y"}]
but my html is not printing anything like key:value .......
you are loading controller many times in a partial.it should not be like that.html code should like this:
<div ng-controller="AddGoalsCtrl">
<h3 ng-repeat="goal in goals" >
<h4 ng-repeat="(key,value) in goal">
{{key}} : {{value}}
</h4>
</h3>
</div>
I created a plunker for you at http://plnkr.co/twdDzpxikJMTe0WuN7ro.
You shouldn't be nesting the controller try something like the following instead:
<body ng-controller="AddGoalsCtrl">
<div ng-repeat="goal in goals">
<h4 ng-repeat="(key,value) in goal">
{{key}} : {{value}}
</h4>
</div>
</body>
Also, don't nest an h tag within another it's not symantically correct HTML. I used a div instead for the outer repeat since you weren't doing anything with it in this example.

Categories

Resources