How to conditionally parse expressions with angular? - angularjs

I have a ng-repeat, which shows conditional sections of markup. However all the expression in the markup are still being parsed and therefore throwing exceptions when they are undefined.
E.G: if item.discriminator is VoteOnNodeRcNotification, the other ng-show will still parse, and for example {{ item.nodeCommentText }} won't exist
i.e: (inside the ng-repeat
<div ng-show="item.discriminator == 'VoteOnNodeRcNotification'" class="type-specific">
<a class="outer-link self-clear" ng-href="{{ nodeLink(item.nodeId, item.nodeText) }}">
<small class="rep-change-mag" ng-class="getAdjustedCss(item.amountAdjusted)">
{{ friendlyAmountAdjusted(item, item.amountAdjusted) }}
</small>
<p class="rep-change-assoc">
Edit accepted: {{ item.nodeText }}
</p>
</a>
</div>
<div ng-show="item.discriminator == 'VoteOnNodeCommentRcNotification'" class="type-specific">
<a class="outer-link self-clear" ng-href="{{ nodeLink(item.nodeCommentId, item.nodeCommentText) }}">
<small class="rep-change-mag" ng-class="getAdjustedCss(item.amountAdjusted)">
{{ friendlyAmountAdjusted(item, item.amountAdjusted) }}
</small>
<p class="rep-change-assoc">
Vote up: {{ item.nodeCommentText }}
</p>
</a>
</div>

You can use ''ng-if'' for that. Just like ng-show, but the content is not generated when the condition is falsy.

ng-show just shows/hides the element, so it still exists in the DOM and therefore will always be evaluated. You can either set a default value for item.discriminator in your controller. For example..
$scope.item = {};
$scope.item.discriminator = null;
null is still falsy and therefore will be hidden by ng-show, but won't throw an error because it is actually defined. Another options is to use ng-if instead of ng-show, which actually removes the element from the DOM when the expression is falsy

Related

Angular ng-show Still Shows <div> Element When Empty

How can I hide/remove the containing <div> element when the value is empty:
<div class="small" ng-show="ID !== ''">{{ info.ID }} | </div>
Renders:
<div class="small">|</div>
Can I remove the <div> completely if empty? I've tried:
<div class="small" ng-show="!ID">{{ info.ID }}</div >
You are checking value of ID property which is not the ID within info object so use info.ID within the ng-show.
<div class="small" ng-show="info.ID">{{ info.ID }} | </div>
<!-- -----------------------^^^^^^^----------------------->
If you don't want to render the element itself then use ng-if directive since ng-show directive simply hide using some CSS.
<div class="small" ng-if="info.ID">{{ info.ID }} | </div>
<!-- ---------------------^^^^^^^----------------------->
If you only want to hide the element then use:
<div class="small" [hidden]="info?.ID">{{ info?.ID }}</div>
If you alse want to avoid rendering it (which is better in most cases) then use:
<div class="small" *ngIf="info?.ID">{{ info?.ID }}</div>
Use the Elvis operator otherwise you may get this mistake:
Can't get ID of null

Geting incorrect $index value for parent ng-repeat loop

I have following code and try to use $index in delete function but it gives incorrect value of it.
<li ng-repeat="joinMember in data.teamMember | orderBy:'member.screenName || member.fname' ">
<div class="member-list-img">
<a ng-href="">
<img ng-src="{{joinMember.member.data.image ? (joinMember.member.data.imageType == 'avatar' ? '/public/images/avatars/' + joinMember.member.data.image : '/public/images/' + joinMember.member.data.image) : '/public/images/avatars/avatar-73.png'}}" width="100%" alt="{{joinMember.member.screenName ? joinMember.member.screenName : joinMember.member.fname + ' ' + joinMember.member.lname }}" />
</a>
</div>
<div class="member-list-cont">
<h4>
<a ng-href="#">
{{joinMember.member.screenName ? joinMember.member.screenName : joinMember.member.fname + ' ' + joinMember.member.lname }}
</a>
</h4>
<span>{{joinMember.created | date : "MMMM d, y"}}</span>
</div>
<div ng-if="data.canModify" class="membr-delete">
<a ng-href="">
<i class="fa fa-trash text_link" aria-hidden="true" ng-click="deleteTeamMember($parent.$index, joinMember.id)"></i>
</a>
</div>
</li>
That's because the directive ng-if creates a new scope for itself, when you refer to $parent, it access the immediate $parent's scope, i.e., the inner repeat expression's scope.
So if you want to achieve something you wanted like in the former, you may use this:
<div ng-repeat="i in list">
<div ng-repeat="j in list2">
<div ng-if="1">
({{$parent.$parent.$index}} {{$parent.$index}})
</div>
</div>
</div>
if you have more than one inner directives, you can use ng-init for storing $index in a variable for references in child scopes.
<div ng-repeat="i in list" ng-init="outerIndex=$index">
<div ng-repeat="j in list2" ng-init="innerIndex=$index">
<div ng-if="1">
({{outerIndex}} {{innerIndex}})
</div>
</div>
</div>
So try $parent.$parent.$index in your example and please check understanding the scopes
You are using $parent.$index in a div that have ng-if tag. which delete dom element(div) if condition is fall so that case you will receive incorrect $index value. but with ng-show it only add hide class to that div.
So try to ng-show if it is not important to remove div element instead just hide it.
Note:- You are also using orderBy filter in ng-repeat which will sort in only your DOM so if you will find incorrect object value in your controller.
As you can see in the official documentation of angularjs you should get a zero-based index via $index within a ng-repeat. Try the example by angularjs here. Try to debug data.teamMember in your controller to make sure that this is the correct array you'd like to iterate.

ng-click - hide all other div that isn't this $index within ng-repeat

What i'm trying to do is similiar to an accordion.
Simple put
i have an ng-repeat with an <a> tag that once clicked show another div called "Printpanel" nested inside it within ng-show.
If the user cick to another <a> tag, i want to hide all other div showed before, and open only to that one related.
I am using $index to trigger the specific div.
Here what i have done:
<div ng-repeat="product in $ctrl.Products">
<a href="#" ng-click="showDetails = $index;>CONFIGURE</a>
<div class="Printpanel ng-hide" ng-show="showDetails == $index" ng-hide="showDetails != $index">
</div>
it seems that ng-hide is not recognized... Anybody have an idea?
You don't need to use ngShow + ngHide: one is enough.
<div class="Printpanel ng-hide" ng-show="showDetails == $index">
You can use ng-if also:
<div class="Printpanel" ng-if="showDetails == $index">
EDIT:
due to scope inheritance problem, you are not able to set showDetails variable. use $parent for that.
working example:
<div ng-repeat="product in $ctrl.Products">
CONFIGURE
<div class="Printpanel" ng-if="$parent.showDetails == $index"> </div>
</div>
seems you have missed closing double quotes here ng-click="showDetails = $index;
Also either of one you need to use ng-show/ng-hide/ng-if = expression

Angular: a part of view does not update

I have a directive template with the following code
<div class="colorpicker">
<div>Chosen color</div>
<div class="color_swatch" style="background-color: {{ngModel}}"> </div>
<div class="clearfix"></div>
<div>Standard colors</div>
<div class="color_squares">
<div ng-repeat="color in colorList">{{color.trim() == ngModel.trim()}} //does not update
<div class="color_swatch" style="background-color: {{ color }};"></div>
</div>
</div>
<div class="clearfix"></div>
In the directive, I update the ngmodel using the below code to the color that was clicked - the div next to "chosen color" is updated with the selected color.
But, the expression "{{color.trim() == ngModel.trim()}}" always amounts to false.
{{color.trim() == ngModel.trim()}}
I have debugged the code and the values are exactly the same.
What I am missing?
This is probably because your variable is precisely named 'ngModel' see that article for more explanation : http://zcourts.com/2013/05/31/angularjs-if-you-dont-have-a-dot-youre-doing-it-wrong/
To resume this article : never use raw fields use always a dot. So in your scope change
$scope.ngModel
By
$scope.data.ngModel
And in your html change ngModel by data.ngModel.
When using dot you may have some undefined error, this is because you have to initialize the object :
$scope.data={};
Of course you can jsut rename your variable, but you may still have a problem with others directives.
I solved this by removing curly braces around color and using ng-style
<div class="color_swatch" id="colorpicker_selected_color" ng-style="{'background-color': selectedColor}" > </div>

AngularJS: change color of a cell based on a condition ng-grid

Here is the plnkr code. I want to change the color of the age cell for all the rows that their alert property is true. I am not sure how to do it. I don't have a separate column for the alert.
Here you go. Refer this modified PLUNKER. Escaping single quote here but indenting the template for better readability.
<div class="ngCellText"
ng-class="{\'green\': row.getProperty(\'alert\') == \'true\' }">
{{ row.getProperty(col.field) }}
</div>
Above case is when alert is the string representation of booleans ("true"/"false"). When alert is boolean, then the template becomes less clumsy:
<div class="ngCellText" ng-class="{\'green\': row.getProperty(\'alert\') }">
{{ row.getProperty(col.field) }}
</div>
UPDATE:
To reduce some verbosity going around there, we can directly use row.entity.alert:
<div class="ngCellText"
ng-class="{\'green\': row.entity.alert == \'true\' }">
{{ row.getProperty(col.field) }}
</div>

Resources