ng-repeat inside directive template won't update during test - angularjs

I have a unit test for an angular directive. This directive has a ng-repeat inside its template which is bound to an array inside the directive's controller. The array changes when a method in the controller is called (this method actually gets called by a sub-directive, something like addMe()).
This works fine in 'real-life', but does not inside a Jasmine unit test. I can see in the debugger, that everything is called and the array has the correct contents, but somehow the ng-repeat won't update. I even tried to call $scope.$digest() inside the controller after a change to the array, but that doesn't work either.
Any help?
Daniel
Relevant part of the template is:
<div class="step-wizard-header">
<div class="step"
ng-repeat="title in titles"
ng-click="selectPage($index, 0)"
ng-class="{ active: currentIndex == $index, done: currentIndex > $index }">
<span class="number">
{{$index + 1}}
</span>
<span class="title">
{{title.text}}
</span>
<div class="substep-holder"
ng-show="currentIndex == $index">
<div class="substep"
ng-repeat="sub in title.subs"
ng-click="selectPage($parent.$index, $index); $event.stopPropagation()"
ng-class="{ active: currentSubIndex == $index, done: currentSubIndex > $index }">
{{sub.text}}
</div>
</div>
<div class="right-arrow"
ng-style="{ 'z-index': (titles.length - $index) }">
</div>
</div>
</div>

The problem was caused by some incompatibility due to the version of ng-animate. Updating everything (to 1.2.13 at the moment) solved the issue.

Related

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

How to access current child ng-repeat object in parent ng-repeat

I'm using Angular 1.5.8 and slick slider 1.6.0. In my project, I have one parent ng-repeat and a child ng-repeat. My slick slider contains one ng-repeat which receives images from API data. My current parent ng-repeat object is referred as 'key' while my current child ng-repeat object is referred as 'thumbkey' (in key.allimages). I need to take current thumbkey object outside slick slider for some manipulations.
(If I could get 'thumbkey' object on 'init' or 'afterchange' event of slider, it would be better as I want to change some values inside the object).
I am using Angular directive for slick "angular-slick-carousel".
<div class="sub-container" ng-repeat="key in getStreamResponse track by $index" pik-id="{{key.pik_id}}">
<!--This code in inside slick slider (Start)-->
<div ng-repeat="thumbkey in key.allimages track by thumbkey.pik_name">
<div class="story-header">
<div class="story-header-pic">
<img class="story-profile-pic" ui-sref="user-profile.story({userid:encodeUserId(key.piklist_user_id)})" src="Resources/spyguy.png" actual-image="{{path}}/profile/{{key.piklist_profile_pic}}" width="40" height="40">
</div>
<div class="story-header-content">
<div class="story-name default-pikmobile-font" ng-show="key.piklist_name != ''" ng-bind="key.piklist_name"></div>
<div class="null-originator-story-name default-pikmobile-font" ng-show="key.piklist_name == ''" ng-bind="thumbkey.user_name"></div>
<div class="story-header-user" ng-if="key.piklist_name != ''">
<span class="normal-text">by</span>
<span class="user-name" disable-sref-if="thumbkey.user_id == selfInfo.id" ui-sref="user-profile.story({userid:encodeUserId(thumbkey.user_id)})" ng-bind="thumbkey.user_name"></span>
<span class="original-user-name" disable-sref-if="thumbkey.originator_id == selfInfo.id" ng-if="(thumbkey.user_name != thumbkey.originator_username) && thumbkey.originator_username != '' "><span class="original-photo-text" ui-sref="story-page({pikid:encodeStoryId(thumbkey.pikd_pik_id)})">Original photo</span> <span class="normal-text">by </span><span class="originator" ui-sref="user-profile.story({userid:encodeUserId(thumbkey.originator_id)})" ng-bind="thumbkey.originator_username"></span></span>
</div>
</div>
<div class="story-upload-time" ng-if="thumbkey.origin_date != '0000-00-00 00:00:00'" ng-bind="getUploadTime(thumbkey.origin_date)"></div>
<div class="story-upload-time" ng-if="thumbkey.origin_date == '0000-00-00 00:00:00'" ng-bind="getUploadTime(thumbkey.date_time)"></div>
</div>
</div>
<!--This code in inside slick slider (End)-->
</div>

using a click listen in angular inside ng-repeat

how do I keep this function from firing/incrementing every single div generated? I only want it to upvote the specific one that I click on. I think the problem is that is inside the ng-repeat.
<div class="text-center" ng-repeat="value in unique">
<span ng-click="incrementUpvotes()">
{{value[0]}} and {{value[1]}} for {{value[2]}} and {{value[3]}} upvotes: {{upvotes}}
</span>
</div>
What I would do is have the function in your controller handle the incrementing of the upvotes, not the actual DOM. Then you can pass in which value you want to be incremented through that function. For example your controller could look like:
function incrementUpvotes(valueNumber){
$scope.value[valueNumber]++;
}
and your HTML like:
<div class="text-center" ng-repeat="value in unique">
<span ng-click="incrementUpvotes(value)">{{value[0]}} and {{value[1]}} for {{value[2]}} and {{value[3]}} upvotes: {{upvotes}}</span>
</div>

Setting ng-click in ng-repeat dynamically

I have a lot of data within ng-repeat. It looks like table with many rows and columns. I want to put ng-click directive on some of cell of table.
Can i put some condition before ng-click directive? If this condition is true - I want to put the directive, otherwise - not to put.
I think you should just put the directive in there and pass it a condition as a parameter which returns boolean. In the directive compile function check if your parameter is right and decide from there what you load.
Maybe this is what you were looking for?
<ul class="menuItems">
<li ng-repeat="item in menuItems">
<div ng-if="item.type == 'link' ">
{{item.name}}
</div>
<div ng-if="item.type == 'function' ">
<span ng-click="function(item.command)" title="item.description">{{item.name}}</span>
</div>
</li>
</ul>

Resources