Using ng-if inside ng-repeat doesn't work - angularjs

I have an array called polls with many objects poll. Each poll has a property moduleState which is initally set to the string "notVoted". The moduleState for an individual poll may later be set to the string "voted". Here is the template for one of my partials:
<div ng-init="loadPage()">
<div ng-repeat="poll in polls">
<div ng-if="poll.moduleState === 'notVoted'">
//Template 1
</div>
<div ng-if="poll.moduleState === 'voted'">
//Template 2
</div>
</div>
</div>
The problem is, both templates are used for each poll in polls. So if there were 3 poll objects in the array polls, the partial would put out:
Template 1
Template 2
Template 1
Template 2
Template 1
Template 2
I suspect this is because of a weird interaction between ng-if and ng-repeat. How can I get it so only one template per poll shows?
Edit: As requested, here is a console.log of a poll object. As you can see, moduleState is in fact set to "notVoted"

Even though this is not the answer but this post represent how should we proceed for troubleshooting this sort of issues.
<div ng-init="loadPage()">
<div ng-repeat="poll in polls">
<span>poll.moduleState: {{poll.moduleState}}</span>
<div ng-if="poll.moduleState === 'notVoted'">
//Template 1
</div>
<div ng-if="poll.moduleState === 'voted'">
//Template 2
</div>
</div>
</div>
note I have introduced test span to check how much time loop iterates and what is the value of that poll object property.
More ever you can also use some chrome extensions that extracts property value from the current runtime ng binding and shows in the developer tool. You can find that tool here. Explore how you can utilize the tool to find out what values are being bind in the dom element and get your issue resolved. :)
Hope this helps you.

Your code is fine ng-if works in ng-repeat:
HTML:
<div>
<div ng-repeat="poll in polls">
<div ng-if="poll.moduleState === 'notVoted'">
<!-- Template 1 -->
Not Voted: {{poll.name}}
</div>
<div ng-if="poll.moduleState === 'voted'">
<!-- Template 2 -->
Voted: {{poll.name}}
</div>
</div>
</div>
</div>
Angular:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.polls =
[
{
"name": "module1",
"moduleState": "notVoted"
},
{
"name": "module2",
"moduleState": "voted"
}
];
});
Here is the fiddle showing ng-if working with ng-repeat: https://jsfiddle.net/AKMorris/nkqkunfr/

I was facing the same problem. honestly still don't know the reason why, but I work it in another way as making it in reverse, for the example above it should be something like :
<div ng-if="poll.moduleState === 'notVoted'">
<div ng-repeat="poll in polls">
//Template 1
</div>
</div>
<div ng-if="poll.moduleState === 'voted'">
<div ng-repeat="poll in polls">
//Template 2
</div>
</div>

Related

AngularJS filter is requiring two clicks before it filters results

I am a beginner at angular. I am pretty certain I am doing this the completely incorrect way but because I finally have it "somewhat working" as it works on the second click I am stuck going in this direction and can't seem to figure out another way to do it.
The filter sorts on the second click because it is initialing as "undefined" before the first click and sets it based on that I believe.
In my html:
<div class="col-xs-12 col-sm-4 location-list" ng-repeat="key in careerlist.location">
<div class="locations" ng-click="careerlist.criteriaMatch()">{{key}}
</div>
</div>
<div class="col-xs-12">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4 job-container" ng-repeat="job in careerlist.career | filter : searchText | filter: selectExperience | filter: careerlist.criteria.name">
<h2>
{{job.title}}
</h2>
<h3>
{{job.location}}
</h3>
<div class="job-description" ng-bind-html="job.description | limitHtml : 200">
</div>
<br><br>
<button>Read More</button>
</div>
<br><br>
</div>
</div>
In my controller:
cl.criteriaMatch = function( criteria ) {
jQuery(document).on('click', '.locations', function(){
cl.criteria = {};
console.log("just the element text " + jQuery(this).text());
cl.criteria.name = jQuery(this).text();
return function( criteria ) {
return criteria.name === criteria.name;
};
});
};
Use ng-click instead of jQuery#on('click'). Angular does not know that the filter should be updated.
Update
#Makoto points out that the click is bound twice. It very much looks like you should just remove the jQuery binding altogether. I would even go so far as suggesting removing jQuery from you project.

How to create div and assign object to dataset dynamically using Angularjs

I have below div (class name 'sp') which I would like to dynamically create based on the sk from a dataset object.
div code
<div style="" class="swindow">
<div class="sp" style="">
<div class="svis" style="">
<div style="height:95%;width:95%;margin-top:0px;margin-left:5px;">
<chart dsn="dyndata" editable="false" labelled="true"></chart>
</div>
</div>
<div class="sdata" style="">
<div class="stext" style="">Average:78% </div>
</div>
</div>
While searching for similar examples, I came across ng-repeat in Angular js and I thought it might suit for this kind of objective.
But am very new to Angular js and not sure how to assign the data to my dyndata variable dynamically and create new div (class=sp) for each of the given id.
Here is the lookup object
[
{"id":20,"st":[{"label":"Audi","value":10},{"label":"BMW","value":70}]},
{"id":26,"st":[{"label":"Benz","value":40},{"label":"BMW","value":20}]},
{"id":12,"st":[{"label":"AUDI","value":60},{"label":"Tesla","value":70}]},
{"id":57,"st":[{"label":"MZ","value":30},{"label":"Honda","value":40}]}
]
When I input the id's as a set [12,26,57] - Three divs (each for #sp) should get created one for each of ids. In those, each div should have the dyndata assigned with the respective 'st' from above javascript object.
I could create div's in jquery using .append function to the container (#swindow) each time when I need. But am not sure how to assign sk as input to dyndata dataset for each div that gets created.
Could you please share how this can be achieved using Angular js ?
Here is the angular js code I used -
<script>
var app = angular.module('ExampleApp', ['ui.plot']);
app.controller('PlotCtrl', function ($scope) {
$scope.dyndata={};
});
</script>
I'm not exactly sure what you're trying to do but I think it should look something like this. Here is a plnkr..
Controller:
app.controller('PlotCtrl', function($scope) {
$scope.items = [
{"id":20,"st":[{"label":"Audi","value":10},{"label":"BMW","value":70}]},
{"id":26,"st":[{"label":"Benz","value":40},{"label":"BMW","value":20}]},
{"id":12,"st":[{"label":"AUDI","value":60},{"label":"Tesla","value":70}]},
{"id":57,"st":[{"label":"MZ","value":30},{"label":"Honda","value":40}]}
]
});
HTML:
<body ng-controller="PlotCtrl">
<div style="" class="swindow">
<div class="sp" style="" ng-repeat="item in items">
<div class="svis" style="">
<strong>{{item.id}}:</strong>
<div>-{{item.st[0].label}}</div>
<div>-{{item.st[1].label}}</div>
<div style="height:95%;width:95%;margin-top:0px;margin-left:5px;">
<chart dsn="dyndata" editable="false" labelled="true"></chart>
</div>
</div>
<div class="sdata" style="">
<div class="stext" style="">Average:78% </div>
<br>
</div>
</div>
</div>
</body>

angular: how to iterate over unlike objects and render different templates

Say I have:
$scope.array = [{type: 'event'}, {type: 'alert'}];
How can I iterate over that and render a different item out of $templateCache for each, based on type. We can assume 'event.html' and 'alert.html' exist.
What other than Keegan's answer you can do is :
<div ng-repeat='a in array'>
<div ng-include="a.type + '.html'"></div>
</div>
This way you get event.html or error.html loaded as per the value
I think what you're looking for is the following.
<div ng-repeat='a in array'>
<div ng-if="a.type =='event'">
// EVENT.html TEMPLATE
</div>
<div ng-if="a.type == 'alert'">
// ALERT.html TEMPLATE
</div>
</div>

Two Way data Binding in Angular js

I am using nodejs + Angular and html as a froentend
Here is my HTML Code
<div id="container" ng-app='two_way' ng-controller='two_way_control'>
<div class="row" ng-repeat="data in profile_pictures">
<div class=".col-sm-6 .col-md-5 .col-lg-6" style="background-color:#eee;height:150px;width:500px;margin-left:240px;margin-top:20px;">
<h4 style="padding:10px;">User Say's</h4><hr>
<img src="{{data.profile_picture}}" class="img-circle" style="width:100px;height:100px;margin-left:-140px;margin-top:-130px;">
</div>
</div>
</div>
and my angular code is here
app.controller('two_way_control',function($scope,$http,$interval){
load_pictures();
$interval(function(){
load_pictures();
},300);
function load_pictures(){
$http.get('http://localhost:3000/load').success(function(data){
$scope.profile_pictures=data;
});
};
});
and my server code is
app.get('/load',function(req,res){
connection.query("SELECT * from user_info",function(err,rows){
if(err)
{
console.log("Problem with MySQL"+err);
}
else
{
res.end(JSON.stringify(rows));
}
});
});
Which is working fine..
When i entered a new record in **user_info*. it will display new record to me.
Is this right way to do two way data binding or i am missing something
Please help.
Thanks
It looks as if you're doing one way binding because your angular code is never modifying the profiles pictures in the table (meaning you ain't got no form fields, your page is read only). But AFAIK you're doing everything right, as soon as you add editing capabilities to your angular page you would be doing two way binding all the way
YES! Angular '2-way bind' is between scope.variable and VIEW (ng-model in input elements).
In this case, the SRC property of IMG element need to be setd with ng-src!
Because IMG is a html element that load before angular principal scripts.
<div id="container" ng-app='two_way' ng-controller='two_way_control'>
<div class="row" ng-repeat="data in profile_pictures">
<div class=".col-sm-6 .col-md-5 .col-lg-6" style="background-color:#eee;height:150px;width:500px;margin-left:240px;margin-top:20px;">
<h4 style="padding:10px;">User Say's</h4><hr>
<img ng-src="{{data.profile_picture}}" class="img-circle" style="width:100px;height:100px;margin-left:-140px;margin-top:-130px;">
</div>
</div>
</div>

AngularJS: data-ng-model & data-ng-hide/show

My index.html page is like as follows:
<div id="sidepanel" data-ng-controller="ListCtrl">
<li data-ng-repeat="record in records">
{{record.id}}
<input type="checkbox" data-ng-model="addwidget">
</li>
</div>
<div id="main">
<div data-ng-view></div>
</div>
for this data-ng-view i have another page recordlist.html in that i have following code:
<div data-ng-controller="ListCtrl">
<ul class="design">
<li data-ng-repeat="record in records">
<div data-ng-switch data-on="record.category">
<div data-ng-switch-when="reporting1">
<div id="{{record.id}}" data-ng-show="addwidget">{{record.description}}</div>
</div>
<div data-ng-switch-when="reporting2">
<div id="{{record.id}}" data-ng-hide="addwidget">{{record.description}}</div>
</div>
</li>
</ul>
</div>
My question is i want to show the first div when i check the checkbox & when i uncheck it i want to show the second div.When both of the data-ng-model & data-ng-hide/show are on the same page then it works fine but in my case it present on two different pages.
Is it correct ? How can i implement this. Need Help.Thanks.
The problem is that you are setting addwidget in the first controller, but is trying to use it in the second. Controllers are not singletons.
So, in this situation:
<div id="sidepanel" data-ng-controller="ListCtrl">
...
</div>
<div id="main">
<div data-ng-view>
<div data-ng-controller="ListCtrl">
</div>
</div>
</div>
You got two separated controllers and scopes. And you are setting addwidget in the first trying to read in the second.
You can either bind it to the root scope $root.addwidget or use a service share to the states.
As you have many records, binding directly to root is a problem, as all of them are going to share the same state. So you gonna need an object in the rootScope and bind the option by id $root.addwidget[record.id]. Made a pretty simplified modification here.

Resources