ng-if inside ng-repeat not working as expected - javascript

I have a repeater that I'm using to return views into an accordion. I'd like to conditionally load the views, so I'm wanting to add an ng-if condition on the repeaters elements to check and see if current == true but it's not working. I'm using Angular 1.0.8.
I have a fiddle
<div data-ng-view></div> is showing all the same view
Edit:
Angular 1.0.8 does not support ng-if so I went with the switch statement.
<div ng-switch="group.current">
<div ng-switch-when="true">
<div data-ng-view></div>
</div>
</div>

Problem was at
<div ng-if="group.current == 'true'"><div data-ng-view></div></div>
replaced with
<div ng-if="group.current === true"><div data-ng-view></div></div>
check updated at http://jsfiddle.net/rajumjib/GUwSh/15/

Related

Is it possible to Angularjs ng-switch does not re render view?

In some page of my site, i have some directives inside ng-switch, like this:
<div ng-switch="contentMenuObj.model">
<div ng-switch-when="calendar">
// Some directive
</div>
<div ng-switch-when="history">
// Some directive
</div>
</div>
Every time that I change the "view" (calendar to history) and go back (history to calendar) the angular re-render the calendar view and new queries are make in the server.
My question is about this behavior, is it possible to angular does not re-render the views? If impossible, what is the best way to solve this problem?
If I understand correctly. You would like to not rerender view when contentMenuObj.model change - right? If so apply one way binding
<div ng-switch="::contentMenuObj.model">
<div ng-switch-when="calendar">
// Some directive
</div>
<div ng-switch-when="history">
// Some directive
</div>
</div>
Model in that case will be loaded only once.
Or try to use ng-show / ng-hide directives if you would like to load directives only once.
<div ng-show="contentMenuObj.model == 'calendar'">
// Some directive
</div>
<div ng-show="contentMenuObj.model == 'history'">
// Some directive
</div>
Angular re-render your directives because ng-switch remove div when ng-switch-when condition is not satisfied, which makes directive is destroy and next time must be re-render.
The ng-show directive in contrast to ng-switch directive not remove element, but only hides.
So, if you want to hide and show content without re-rendering, try:
<div>
<div ng-show="contentMenuObj.model === 'calendar'">
// Some directive
</div>
<div ng-show="contentMenuObj.model === 'history'">
// Some directive
</div>
</div>

angular polymer if else condition for div element

i have polymer template in which i have 3 divs . i want to keep condition on based on name m fetching in expression. How to keep condition for the same.
code is below:
<div class="cySimplifiedContainer isCostLabel">
<span>{{item.id.optnName}}</span>
</div>
<div class="isSummary">
<span class="iSHeader">{{_toMoneyFormat(item.optnCtd)}}</span>
</div>
<div class="isSummary">
<span class="iSHeader">{{_toMoneyFormat(item.optnGoFwd)}}</span>
</div>
<div class="isSummary">
<span class="iSHeader">{{_toMoneyFormat(item.optnTotal)}}</span>
</div>
I need to keep check on item.id.optnName . If it contains KEFH then it should remove _toMoneyFormat function from span.
plz review .
use ng-if in your div. Here i create a simple ng-if example
plnkr here
for more information read AngularJS/ng-if doc

class swapping with angular

I am opening and closing some side (open and close under the title) using angular and I'm wondering if there is a way I can swap between classes When I'm doing this too so I can swap some css. Here's what I'm doing -
<form name="metaDeta" id="lessonDetails" class="lessonItem" ng-controller="detailsController">
<div class="small-12 columns">
<div class="lesonHead lessonHeadOpen saDetailsHead" ng-click="showDetails = ! showDetails" ng-class="myVar">
<h5>Lesson Details</h5>
</div>
<div class="lessonSASlider" ng-show="showDetails">
This works fine for opening and closing the form, however there is a class .lessonHeadOpen that I would like to try and toggle between .lessonHeadClosed. So basically I am looking for something like an addClass/removeClass even on click to toggle between the 2 classes on the element when the user opens and closes it. Is this possible with angular? Could I work off what I have or do I have to re-structure. Thanks!
You can use ng-class to dynamically add classes based on the result of expressions. Read ngClass
<div class="lessonHead" ng-click="showDetails = ! showDetails">
<h5>Lesson Details</h5>
</div>
<div ng-class="{className: showDetails}">
</div>
This directive will evaluate showDetails expression and if true, it will apply the class className
Update:
If I understand correctly, do the same but reverse the expression so if not showdetails add one class and then when show details is true it will be removed and the other class added. <div ng-class="{classOne: showDetails , classTwo: !showDetails}"> SEE FIDDLE
You can use ng-class for toggling.
Simply add a condition for a class to appear and it will based on the condition.
ng-class="{'className': shouldShowClass}"
You can use ng-class's ternary operator notation:
<div ng-class="showDetails? 'lessonHeadOpen': 'lessonHeadClosed'>...</div>
SAMPLE DEMO

Cascading expression in AngularJS works with ng-show but not with ng-if

The following block of code work if I use ng-show to display sections but not with the desired ng-if
<div ng-controller="nullController">
<button ng-click="p = 1">click to reveal next</button>
</div>
<div ng-show="$$prevSibling.p == 1" ng-controller="nullController">
<div>Appears based on previous sibling state</div>
<button ng-click="p = 1">click to reveal next</button>
</div>
<div ng-show="$$prevSibling.p == 1" ng-controller="nullController">
<div>Appears based on previous sibling state</div>
<button ng-click="p = 1">click to reveal next</button>
</div>
See in Plunker ng-show
See in Plunker ng-if
UPDATE: someone pointed out that the version of the angularjs lib in the plank did not have ng-if. Now I have updated to use 1.2.x the problem however did not go away.
You are using angularjs 1.0.1 !
ng-if didn't exist in this old version yet.
Only the versions above 1.1.5 handle the ng-if directive.
You really should rather choose this version (the latest stable one) for your plunkr for instance:
<script data-require="angular.js#1.2.16" data-semver="1.2.16" src="https://code.angularjs.org/1.2.16/angular.js"></script>
Here's a more official data to show that ngIf was available since 1.1.5.
Furthermore, pay attention that ngIf creates a new child scope.
Indeed, it needs this mechanism in order to achieve the delete of the component from the DOM.
ng-show does not need it since it simply hide the content.
Thus, $$prevSibling would not target the expected scope, since called from a deeper scope in the scopes' hierarchy.

Conditional logic in AngularJS template

I have an angular template which looks like this...
<div ng-repeat="message in data.messages" ng-class="message.type">
<div class="info">
<div class="type"></div>
<div class="from">From Avatar</div>
<div class="createdBy">Created By Avatar</div>
<div class="arrowTo">
<div class="arrow"></div>
<div class="to">To Avatar</div>
</div>
<div class="date">
<div class="day">25</div>
<div class="month">Dec</div>
</div>
</div>
<div class="main">
<div class="content">
<div class="heading2">{{message.title}}</div>
<div ng-bind-html="message.content"></div>
</div>
</div>
<br />
<hr />
<br />
</div>
I have set up a JSfiddle to show the data being bound.
What I need to do is make the "from", "to" and "arrowTo" divs show conditionally, depending on the content of the data.
The log is is this...
If there is a "from" object in the data then show the "from" div and bind the data but don't show the "createdBy" div .
If there is no "from" object but there is a "createdBy" object then show the "createdBy" div and bind the data.
If there is a "to" object in the data then show the "arrowTo" div and bind it's data.
Or in plain English, if there is a from address, show it, otherwise show who created the record instead and if there is a to address then show that too.
I have looked into using ng-switch but I think I'd have to add extra markup which would leave an empty div if there was no data. Plus I'd need to nest switch directives and I'm not sure if that would work.
Any ideas?
UPDATE:
If I were to write my own directive (If I knew how!) then here is some pseudo code to show how I would want to use it...
<div ng-if="showFrom()">
From Template Goes Here
</div>
<div ng-if="showCreatedBy()">
CreatedBy Template Goes Here
</div>
<div ng-if="showTo()">
To Template Goes Here
</div>
Each of these would disappear if the function/expression evaluated to false.
Angular 1.1.5 introduced the ng-if directive. That's the best solution for this particular problem. If you are using an older version of Angular, consider using angular-ui's ui-if directive.
If you arrived here looking for answers to the general question of "conditional logic in templates" also consider:
1.1.5 also introduced a ternary operator
ng-switch can be used to conditionally add/remove elements from the DOM
see also How do I conditionally apply CSS styles in AngularJS?
Original answer:
Here is a not-so-great "ng-if" directive:
myApp.directive('ngIf', function() {
return {
link: function(scope, element, attrs) {
if(scope.$eval(attrs.ngIf)) {
// remove '<div ng-if...></div>'
element.replaceWith(element.children())
} else {
element.replaceWith(' ')
}
}
}
});
that allows for this HTML syntax:
<div ng-repeat="message in data.messages" ng-class="message.type">
<hr>
<div ng-if="showFrom(message)">
<div>From: {{message.from.name}}</div>
</div>
<div ng-if="showCreatedBy(message)">
<div>Created by: {{message.createdBy.name}}</div>
</div>
<div ng-if="showTo(message)">
<div>To: {{message.to.name}}</div>
</div>
</div>
Fiddle.
replaceWith() is used to remove unneeded content from the DOM.
Also, as I mentioned on Google+, ng-style can probably be used to conditionally load background images, should you want to use ng-show instead of a custom directive. (For the benefit of other readers, Jon stated on Google+: "both methods use ng-show which I'm trying to avoid because it uses display:none and leaves extra markup in the DOM. This is a particular problem in this scenario because the hidden element will have a background image which will still be loaded in most browsers."). See also How do I conditionally apply CSS styles in AngularJS?
The angular-ui ui-if directive watches for changes to the if condition/expression. Mine doesn't. So, while my simple implementation will update the view correctly if the model changes such that it only affects the template output, it won't update the view correctly if the condition/expression answer changes.
E.g., if the value of a from.name changes in the model, the view will update. But if you delete $scope.data.messages[0].from, the from name will be removed from the view, but the template will not be removed from the view because the if-condition/expression is not being watched.
You could use the ngSwitch directive:
<div ng-switch on="selection" >
<div ng-switch-when="settings">Settings Div</div>
<span ng-switch-when="home">Home Span</span>
<span ng-switch-default>default</span>
</div>
If you don't want the DOM to be loaded with empty divs, you need to create your custom directive using $http to load the (sub)templates and $compile to inject it in the DOM when a certain condition has reached.
This is just an (untested) example. It can and should be optimized:
HTML:
<conditional-template ng-model="element" template-url1="path/to/partial1" template-url2="path/to/partial2"></div>
Directive:
app.directive('conditionalTemplate', function($http, $compile) {
return {
restrict: 'E',
require: '^ngModel',
link: function(sope, element, attrs, ctrl) {
// get template with $http
// check model via ctrl.$viewValue
// compile with $compile
// replace element with element.replaceWith()
}
};
});
You can use ng-show on every div element in the loop. Is this what you've wanted: http://jsfiddle.net/pGwRu/2/ ?
<div class="from" ng-show="message.from">From: {{message.from.name}}</div>

Categories