Displaying a blank ng-repeat on purpose (for a nested array) - angularjs

I'm iterating (ng-repeat) over a childArray of an existing loop with ng-repeat, but I want blank results to show on my child ng-repeat. Is there any way to do that? I have an element structure I want to be shown from the child ng-repeat.
The code looks like this :
<ng-repeat="row in parentArray"> <--- the parent array
{{row.name}}
{{row.date}}
{{row.place}}
<ng-repeat="option in row"> <--- the child array
Result : {{option.name}} <-- I still want result to show up
</ng-repeat>
</ng-repeat>

If i understand you correctly, you wanna show something if there is no option?
ng-repeat only works with data. When there is no data, nothing is displayed. For this purpose you can use ng-if or ng-show / ng-hide
Also it is very unclear for me at the moment, where the options are stored in the row
HTML
<ng-repeat="row in parentArray"> <--- the parent array
{{row.name}}
{{row.date}}
{{row.place}}
<div ng-if="row.options.length > 0">
<ng-repeat="option in row.options"> <--- the child array
Result : {{option.name}} <-- I still want result to show up
</div>
<div ng-if="row.options.length === 0">
<label>No Data</label>
</div>
</ng-repeat>

Related

When ng-init in ng-repeat is replays?

I have a simple ng-repeat to build a HTML list from a javascript array.
Each item can be moved using an input to get the new rank. This input is binded to a variable rank. This variable is initialized using the ng-init directive.
Code looks like this :
<li ng-repeat="item in ctrl.getItems()">
<div ng-init="rank = $index">
[$index: {{$index}}]
{{item}}<br/>
<label>
Move to
<input type="number" ng-model="rank"/>
</label>
<button type="button" ng-click="ctrl.moveItem($index, rank)">
Ok
</button>
</div>
</li>
At runtime, when I change the input value and click to the Ok button, function ctrl.moveItem is called and item is really moved in the ctrl.getItems() array.
So the ng-repeat is replayded and items appears in the new order.
BUT variable rank is not reinitialized and 2 items appears with the same rank.
The sample is here : https://jsfiddle.net/nlips/4ng34b7b/
My question is not so much about moving items in a list, but I need to understand how ng-init works in the context of ng-repeat.
I did not find anything on this subject in the AngularJS official documentation.
From AngularJS docs:
The ngInit directive allows you to evaluate an expression in the current scope.
Now. You are working with different scope.
You are using ngInit into the transcluded scope, overriding $scope.rank each time it repeats that portion of template.
If you want to persist your rank you should init it into the ngRepeat scope.
Try with:
<li ng-repeat="item in ctrl.getItems()" ng-init="rank = $index">
[$index: {{$index}}]
{{item}}<br/>
<label>
Move to
<input type="number" ng-model="rank"/>
</label>
<button type="button" ng-click="ctrl.moveItem($index, rank)">
Ok
</button>
</li>
EDITED ANSWER
Ok, i got it.
The ngInit expression is evaluated only when that part of template is going to be rendered into the DOM.
So, when the page is loaded for the first time your expression is fired and each rank is evaluated correctly.
But, when you make changes on an item that is already rendered, your template is not going to be rendered again, so your ng-init will not be fired.
If you want that ng-init to be executed again you have to remove the item from the DOM and then append it back, into the new position.
There are several alternatives to this approach, but i hope this clarifies what was going on.

Hide empty slots in nested array using AngularJS

In my ionic app, I want to show a cart. My problem is empty objects in my nested array.
My array look like this:
array [0:{id:0,
name:meal,
item:[0:{id:0,name:pizza0,count:1},
2:{id:2,name:pizza2,count:3}]}
1:{id:1,
name:meal,
item:[0:{id:0,name:drink0,count:1},
1:{id:1,name:drink1,count:5}]}
]
My html code look like this:
<div ng-repeat="cart in carts">
<ion-item class="item-stable">
<!-- breaking space-->
{{cart.name}}
</ion-item>
<ion-item class="item-accordion" ng-repeat="item in cart.item track by $index">
<ion-delete-button class="ion-minus-circled" ng-click="removeFromCart(item,cart.id)"></ion-delete-button>
{{item.count}}x {{item.name}} - {{item.length}}
<ion-item>
The result looks like this:
I try to hide the empty arrays with ng-if:
ng-if="cart.item.length > 0"
ng-if="item.name"
With the first, no item shows (probably because cart.item.length is undefined).
With the second all items are shown.
What am I doing wrong? Is there a better way to hide empty arrays?
You can use safe navigation operator with ngIf directive.
use ngIf in div tag like this:
*ng-If="item?"
This will only hide the empty items and only show items with data in it.

Element not updated with calculated value in Angular.js v 1.0.7

When I load a page to display items prices, before the prices are calculated in the controller the page displays "null" in the price for a while (maybe 1 sec). How can I avoid this? I thought this is the purpose of ng-init, is it right?
When I use it, I get my items initialized to 0. This is ok. However, when the value is calculated the price is not updated.
Example:
<div class="text-right custom_block_field" ng-show="booking.duration == 0" ng-init="itemSelected.convertedPrice = 0">{{(itemSelected.convertedPrice)}}</div>
ng-init is not for that, it is basically used to call a method or some initialization of the values
<div class="text-right custom_block_field"
ng-show="booking.duration == 0"
ng-bind="itemSelected.convertedPrice"></div>
Or use the ng-cloak with parent element
ng-cloack is the best way. It'll mask a value until it's ready.
<div ng-cloak>
//whatever your app code is
</div>

Get data inside an ng-repeat from an directive outside of it

I'm developing a mobile application using Ionic Framework based an AngularJS.
On one directive I'm looping over a JSON Array with ng-repeat applying a condition with ng-if, see below:
<ion-content class="has-header has-subheader" >
<ion-slide-box">
<ion-slide
ng-if="invocation.title_id == titleid"
ng-repeat="invocation in invocations" >
<h3>{{invocation.id}}</h3>
<div ><h1>{{invocation.invocation_frensh }}</h1></div>
<div ><h1>{{invocation.invocation_ar}}</h1></div>
<div ><h1>{{invocation.invocation_franko}}</h1></div>
<div ><h1>{{invocation.comments_fr}}</h1></div>
<div ><h1>{{invocation.comments_ar}}</h1></div>
</content>
</ion-slide>
</ion-slide-box>
<p>{{invocation.id}}</p>
</ion-content>
The point is that on the last p nothing is shown.
I understand that the $scope is not the same but on the last "p" or any other component outside the ng-repeat I need to have the same data in order to interact with it.
For exemple I want to add a button on a footer that gets the "{{invocation.id}}". If invocation.id equals 3 inside the ng-repeat "h3" I want to have it equals 3 in the "p"
How can i do it ?
Thanks for you help
Edit: In fact I want invocations[index].id in the 'p' outside of the loop, where index equals the displayed slide.
the invocation variable dies when the ng-repeat ends, if you need to use it again, you will need another ng-repeat
Assuming that you want to show only one slide at a time, you could do it without ng-if, and use filter instead.
<ion-slide ng-repeat="invocation in displayedInvocations = (invocations | filter:{title_id: title_id}:true)">
and then at outside:
<p>{{displayedInvocations[0].id}}</p>
Hope this helps.

Bound Input gets unfocused in angularjs

I am running this simple code with angularjs :
HTML :
<div ng-app ng-controller="AController">
<code>{{ itemsInArray }}</code>
<div ng-repeat="item in itemsInArray">
<input ng-model="itemsInArray[$index]" />
</div>
</div>
JavaScript :
function AController($scope) {
$scope.itemsInArray = ["strA", "strB", "strC"];
}
Binding appears to be working correctly when indexing into the array but after entering one character the input loses focus.
You can find the working code here on this fiddle : http://jsfiddle.net/QygW8/
I think this is happening because you are manipulating the same item which is iterated over ng-repeat. So ng-repeat sees a change in the item and re-runs the `ng-repeat which regenerates the items.
If you look at your fiddle html, you may notice this effect.
To make it work, one way you can do this
http://jsfiddle.net/cmyworld/CvLBS/
where you change your array to object array
$scope.itemsInArray = [{data:"strA"}, {data:"strB"}, {data:"strC"}];
and then bind to item.data
Try to change the model:
<div ng-repeat="item in itemsInArray">
<input ng-model="item" />
</div>
Even am an newbie to the angularjs, up-to my findings ng-repeat updates/repeats and recreates the whole HTML elements when there is an change in the model. Hence when a single character added to model causes ng-repeat to react and creates the all the HTML elements again which results to losing the focus.
This is an fiddle , In which u will be able to observer the changes with the model inside the ng-repeat and outside the ng-repeat.
Sorry i don't have the solution, Hope using ng-change apart of ng-model may help.

Resources