ng-repeat and ng-click not playing well - angularjs

<li ng-repeat="item in data" ng-click="myFunc('{{ item.name }}')">
I can't seem to get ng-click to pass the varible value of item.name. It actually sends:
{{ item.name }}
An example in Plunker:
http://plnkr.co/edit/dq5KA3?p=preview
In the console it looks ok, but doesn't actually work:

ng-click is actually an angularjsexpression, so you should be able to set it as ng-click='myFunc(item.name)'. This will pass the actual value of item.name rather than trying to pass the string value of the raw text as your current implementation is doing.

Use:
<li ng-repeat="item in data" ng-click="myFunc(item.name)">{{item.name}}
</li>
Because item is an object.
Explanation about the results in the console, in your scenario:
Always: {{item.name}} It will print the value, this is why you see in the console:
<li ng-repeat="item in data" ng-click="myFunc('Apple')" class="ng-binding ng-scope">Apple
</li>
Because you have in your page:
<li ng-repeat="item in data" ng-click="myFunc('{{ item.name }}')">{{item.name}}
</li>

ng-click is actually an angular directive not an expression, you need to give brackets when you are passing value to the expression but you do not need to use brackets when you pass values to directive.

Related

Why nothing is displayed in list initially when i use ! (not) in AngularJS filter?

<p><input type="text" ng-model="test"></p>
<ul>
<li ng-repeat="x in names | filter:'!'+test">
{{ x }}
</li>
</ul>
How to display all the items in list initially and then exclude the items as i type? Initially, none of the items are displayed. Only after i type something in textbox, it displays the items excluding the one which i typed.
You are missing angularjs strict:true operator in filters
this is what you need
<li ng-repeat="x in names | filter:'!'+test:true">
{{ x }}
</li>
Plnkr
On top of my head setting an initial value in model $scope.test = '' should resolve the issue for you.
No need of this '!' ,you just have to pass ng-model value
<p><input type="text" ng-model="test"></p>
<ul>
<li ng-repeat="x in names | filter:test">
{{ x }}
</li>
</ul>

Setting start index to loop in AngularJS

I am developing a Web application using AngularJS. I am having a problem to use for loop in the html in AngularJS way. See my scenario below.
In AngularJS, we normally loop ng-repeat like this
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
But what I want to do is I want to set the start index for loop. In JavaScript, it is going to look like this.
for(var i=3;i<items.length;i++)
{
//do something
}
As you can see, I set the start index(i) to 3. But how can I embed the code in html in AngularJS way? What I want is something like setting start index to ng-repeat. Is it possible to do that?
If you use JavaScript's Array.slice function, you won't need to invoke Angular functions.
<ul>
<li ng-repeat="item in items.slice(3)">{{ item.name }}</li>
</ul>
ng-repeat="item in myItems" ng-if="$index>=3"
<ul>
<li data-ng-repeat="item in items | limitTo: (startIndex - items.length)">
</ul
This will work.

How to pass an ng-repeat iterator to ng-click

I have created this snippet in AngularJS that displays a pagination bar on my web page. The object $scope.PagesOnBar contains an array of numbers like 1, 2, 3 which are appearing on the pagination bar. The problem is in my ng-click attribute; the value {{x}} gets passed as a literal - the x is not replaced with 1, 2, 3. How can I re-write this so that the numeric value is passed to the BarClick function? I tried putting ng-repeat before ng-click and that didn't work either. I also tried removing the curly braces - same result.
<ul class="PaginationBar">
<li class="FloatLeft" ng-click="BarClick('<<');"><<</li>
<li class="FloatLeft" ng-click="BarClick('<');"><</li>
<li class="FloatLeft" ng-click="BarClick('{{x}}');" ng-repeat="x in PagesOnBar">{{x}}</li>
<li class="FloatLeft" ng-click="BarClick('>');">></li>
<li class="FloatLeft" ng-click="BarClick('>>');">>></li>
</ul>
<ul class="PaginationBar">
<li class="FloatLeft" ng-click="BarClick('<<');"><<</li>
<li class="FloatLeft" ng-click="BarClick('<');"><</li>
<li class="FloatLeft" ng-repeat="x in PagesOnBar" ng-click="BarClick(x)">{{x}}</li>
<li class="FloatLeft" ng-click="BarClick('>');">></li>
<li class="FloatLeft" ng-click="BarClick('>>');">>></li>
</ul>
Most ng directives don't need curly braces ({{ }}) to understand that you're referring to some sort of expression or variable.
Also, this may be just my preference, but I tend to declare the ng-repeat loop before I ever try to reference the iterated variable. It may be that Angular will still understand it, but at least for reading, it makes more sense to declare it first.
If you don't want a literal, don't enclose x in '... Just write x

How to iterate through an array of arrays in JSON using ng-repeat?

I am trying to iterate over a JSON object userTypes.
For the below code:
In the 1st ng-repeat:
{{user.type}} outputs 'Parent'(as expected),
{{user.options}} outputs '[{"option1":"11QWERT","option2":"22QWERT"}]'(as expected).
But in the 2nd ng-repeat, I am not able to iterate through the user.options and output each of the {{options}}
What should be changed to get the option1 and option2 as the outputs in 2nd ng-repeat ?
JS snippet
var userTypes = [{
"type": 'Parent',
"options": [{
"option1": "11QWERT",
"option2": "22QWERT"
}]
}]
HTML snippet
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<p>{{user.options}}</p>
<li ng-repeat="option in user.options">
<p>
{{option}}
</p>
</li>
</li>
Replace your child <li> with <ul> and then you can iterate user.options like so:
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<ul ng-repeat="(key, value) in user.options[0]">
<p>{{key}}: {{value}}</p>
</ul>
</li>
Or if your options may include more then one object:
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<ul ng-repeat="option in user.options">
<li ng-repeat="(key, value) in option">{{key}}: {{value}}</li>
</ul>
</li>
If you don't need object keys:
<ul ng-repeat="option in user.options">
<li ng-repeat="item in option">{{item}}</li>
</ul>
Fiddle
Extended explanation:
In your example you have <li> tag inside another <li>:
<li ng-repeat="user in userTypes">
<li ng-repeat="option in user.options">
</li>
</li>
Since it is not a valid HTML browser will interprets this markup to following:
<li ng-repeat="user in userTypes">
</li>
<li ng-repeat="option in user.options">
</li>
Since ng-repeat creates new scope for each iteration you can't access user variable in second ng-repeat and iterator wouldn't run.
For this exact JSON input it should be like this:
<li ng-repeat="option in user.options">
<p>
{{option.option1}}
{{option.option2}}
</p>
</li>
However as you said you want non fixed number of options, update your JSON to be like this:
"options":["11QWERT","22QWERT"]
And then your code should work as you wanted it.
You can add each new element to list with simple coma before it.
Since user.options is an array you should loop it again. By doing that you will get an object, with that object you can access your options1 and option2 easily.
please refer working plunker:
http://embed.plnkr.co/5c3i5fY50jLP0fFgxkUX/preview
see through the code if you have any doubt.
Hope this helps
A little aside, but just found out you can render a valid list HTML using ng-repeat-start/end in combination with ng-if="false" for the given array of arrays to flatten them:
<ul>
<script ng-repeat-start="user in userTypes" ng-if="false"></script>
<li ng-repeat="item in user.options">{{item}}</li>
<script ng-repeat-end="" ng-if="false"></script>
</ul>
Just access the propertie of the option object in the second ng-repeat. Like option.option1
You should probably make your user.options an object and not an array containing a single object.
Note the difference between these:
[{"option1":"11QWERT","option2":"22QWERT"}]
{"option1":"11QWERT","option2":"22QWERT"}
You can then iterate the options with an ng-repeat like discussed here:
<li ng-repeat="(key, value) in user.options">
<p>{{ key }}: {{ value }}</p>
</li>

Do bindings nested inside of a lazy one-time ng-repeat binding bind just once?

My understand is that in the following code, both bindings will lazily bind only once:
<li ng-repeat="item in ::items">{{::item.name}}</li>
However, in the following case will {{item.name}} be updated every digest?
<li ng-repeat="item in ::items">{{item.name}}</li>
And how does one-time binding effect nested ng-repeats ?
<li ng-repeat="item in ::items">
<span ng-repeat="thing in item.things">{{thing.name}}</span>
</li>
Scenario 1:
<li ng-repeat="item in ::items">{{::item.name}}</li>
Both expressions will be one-time bound. Adding an item or changing an existing item's name will not be reflected.
Demo: http://plnkr.co/edit/53r8FCmcNK4MmM6Uzxp2?p=preview
Scenario 2:
<li ng-repeat="item in ::items">{{item.name}}</li>
First expression will be one-time bound. Adding an item will not be reflected. Changing an existing item's name will be reflected.
Demo: http://plnkr.co/edit/52wTEb8ze2FKRDDcS9Ow?p=preview
Scenario 3:
<li ng-repeat="item in ::items">
<span ng-repeat="thing in item.things">{{thing.name}}</span>
</li>
First expression will be one-time bound. Adding new item will not be reflected. Adding a new thing and changing existing thing's name will be reflected.
Demo: http://plnkr.co/edit/HkObhkJtUnFEHBAzFUmN?p=preview

Resources