Toggling boolean variable from nested AngularJS or Ionic directives - angularjs

I have a nested list to display comments and replies with 3 levels. I'm toggling dates from time-ago to actual on click by showing and hiding one of two date elements. This works well for each level using ng-click="$parent.swapDate=!$parent.swapDate", but fails to affect other levels.
How can I apply the toggle to all levels of the structure, which looks like the following (simplified)?
<ion-content>
<div class="list">
<div class="item" ng-repeat="comment in comments">
<span am-time-ago="comment.date | amUtc | amLocal"
ng-click="$parent.swapDate=!$parent.swapDate"
ng-hide="$parent.swapDate">
</span>
<span ng-click="$parent.swapDate=!$parent.swapDate"
ng-show="$parent.swapDate">
{{comment.date | amDateFormat: 'D MMMM YYYY # h:mma'}}
</span>
<div class="list">
<div class="item" ng-repeat="comment in comments">
<span am-time-ago="comment.date | amUtc | amLocal"
ng-click="$parent.swapDate=!$parent.swapDate"
ng-hide="$parent.swapDate">
</span>
<span ng-click="$parent.swapDate=!$parent.swapDate"
ng-show="$parent.swapDate">
{{comment.date | amDateFormat: 'D MMMM YYYY # h:mma'}}
</span>
</div>
</div>
</div>
</div>
</ion-content>
I'd prefer to not use a global variable or a service for such a simple thing. Thank you.

inside ng-click or ng-hide or other ng-xx,the $parent.var become isolated once you change it;thus other div won't change. try put it in an object e.g. $parent.var_obj={var:xx}

Marks' answer helped send me in the right direction. Actually, I was reading a good article that mentions the 'dot' best practice for scope variables, and I returned to this question to investigate.
Simply replacing
$parent.swapDate
with
comments.swapDate
in all instances resolves the problem.

Related

Why does ng-click not fire functions when inside ng-repeat, in AngularJS?

I am working on a small AngularJS application. In one of the views, I have replaced some hard-coded html with data coming from a JSON file that I iterate through:
<class="actions-list">
<div ng-repeat="item in $ctrl.myCustomService.config.items"
ng-class="{'disabled': !item.isEanabled}"
class="actions-item"
ng-click="$ctrl.selectAction('{{item.action}}')">
{{item.name | translate }}
</div>
</div>
The problem is that, since this replacement, the function fired by ng-click, that used to be (hard-coded) ng-click="$ctrl.selectAction('register'); and so on, does not work anymore.
Why does that happen? How can I fix the problem?
You don't need quotes or {{ }} inside ng-click:
<class="actions-list">
<div ng-repeat="item in $ctrl.myCustomService.config.items"
ng-class="{'disabled': !item.isEanabled}"
class="actions-item"
ng-click="$ctrl.selectAction(item.action)">
{{item.name | translate }}
</div>

Why is ng-repeat one time binding not working in AngularJS?

After doing most of my testing in Chrome, I have discovered my site is running like a dog in IE 11
After some investigation I am trying to use one time binding on my ng-repeats, however when I use the double colon syntax nothing renders on my page
Here is a snippet
<div data-ng-repeat="i in [1,2,3,4,5,6,7,8,9]">
<div id="Raiders{{$index + 1}}" ng-repeat="player in ::players | filter:{ Team:'Raiders', Group: $index + 1}">
<div style="white-space:nowrap">
<span ng-click="updateTeam(player)">{{::player.FullName}}</span>
<span class="statsFootball" ng-click="showTabDialog(player)"></span>
</div>
</div>
</div>
My only change has been to use :: (double colon) in my ng-repeat statement and also to print player.FullName
I am using Angular 1.5.8
I'm not sure why this doesn't work.

AngularJS: show time from datetime

I am using Angular in a web application. I am showing some placed orders by users with following code. And this works just fine:
<div class="orderspresent" ng-cloak="">
<div class="roworders" style="margin-bottom:5px;" ng-controller="allorders" >
<div class="col-md-3" ng-repeat= "o in orders | orderBy:-o.orderID" ng-hide= "o.orderStatus=='done'" ng-hide="hidden" ng-class="{fade: startFade}">
<div class="sm-st clearfix">
<div class="sm-st-info">
<i class="fa fa-square"></i>
<input type="checkbox" ng-true-value="{{o.orderID}}" ng-change="stateChanged({{o.orderID}})" ng-model="status"/>
</div>
<span>{{o.customerName}}</span>
<p>{{o.orderDate | date:'h:mm'}}</p>
<ul>
<li ng-repeat= "details in o.details">
{{details.aantal}} x {{details.productTitle}}
<div ng-if="details.extras">
+{{details.extras}}
</div>
</li>
<p class="totalprice">{{getTotal()}} euro</p>
</div>
</div>
But for each of these orders I want to show the time they got ordered. I tried using {{o.orderDate | date:'h:mm'}} but this doesn't seem to do anything... How can I only show for example: 10:06 or 12:10?
JSON Data
[{"orderID":49,"customerID":61,"orderDate":"2015-05-06 10:03:05","orderDeliveryDate":"2015-05-06 10:30:05"}, ...]
Looks like the string you are passing into date filter is not valid ISO 8601 datetime string so the filter can't handle it. The closest to your orderDate strings applicable format would be something like yyyy-MM-ddTHH:mmZ. So you can either make your strings to look like '2015-05-06T10:03:05' or convert them to Date objects before passing to template: new Date('2015-05-06 10:03:05').
Here is a little demo of the difference: http://plnkr.co/edit/t2nk1qS4SMvGPzeSi3eC?p=preview

DOM manipulation before the template gets modal data

I've a situation where I want to display an error message on the page when my modal don't have any records to show. This could be on the initial load or after applying some filter criteria on the page.
I'm using ng-if to check the count of records on the result set after applying the filter, that is why when my page initially loads as there is no data in the filtered result rest it is showing up the error message first and then later it is showing the data.
Any insight would be highly appreciated
prod.skulist is my modal.
<ul class="prd-list">
<li ng-repeat=" p in filtered =(prod.skulist | categoryFilter:prod.selectedFormat :prod.selectedRating) | filter :priceRange" id=" {{p.sku}}">
<figure class="prd-img" ng-click="wrapCtrl.showProdDetils(p.sku,prod.catName)">
<div style="background-image: url({{wrapCtrl.imageLocation+p.image}}); background-repeat: no-repeat;"></div>
<figcaption class="prd-nam f8">{{p.title}}</figcaption>
<span class="new-item" ng-show="{{p.isnew}}"><img src="Content/images/new.png" /></span>
<span class="new-item" ng-show="wrapCtrl.compareStreetDate(p.streetdate)"><img src="/Content/images/coming-soon.png" /></span>
</figure>
<div class="prd-price f5">
{{p.currentprice | currency}}<span class="sales" ng-show="{{p.onsale}}">ON SALE</span>
<span class="cart-btn" ng-click="wrapCtrl.addCart($event)"></span>
<div class="inactive-cart-btn" ng-show="wrapCtrl.compareStreetDate(p.streetdate)"></div>
</div>
</li>
</ul>
<div ng-if="(filtered | filter :priceRange).length ==0" class="error-box">
<div class=" wrp"><span class="error-head">I hate when this happens</span></div>
<div class="wrp error-message">
<span class="f9 pad-top">It looks like I don't have exactly what you are looking for.</span>
<span class="f9 pad-bot">try adjusting your filters to see more</span>
</div>
</div>
I ran into a similar situation and found an ugly, though working solution by using the $timeout service. In your case you would have a scope variable, lets call it loadTimeGiven = false and after the $timeout you set it to true. Then simply do
ng-if="(filtered | filter :priceRange).length ==0 && loadTimeGiven"
Alternatively you could set loadTimeGiven based on a service that your modal has access to.

ng-repeat filter and repeat by heading

Trying to separate a group of filters that come back from a search that I am doing in my angular app. When I do the search i receive back the json and it is grouped by heading. Can I only repeat the items in that particular group and separate them that way? The reason is that each group will be in a unique UI module. So some of the list will be returned and displayed in a slider and some will be in radios.
Here is the:
<div heading="{{filter.name}}"
ng-repeat="filter in inventory.filters | filterOptions | orderBy:'name'"
is-open="true" show-attrs>
<h3>{{filter.name | uppercase}}</h3>
<div ng-repeat="option in filter.options">
<span ng-click="selectedFilter(filter, option.option, option.id)">
<a>{{option.option}}{{option.count>0 ? "("+option.count +")": ""}}</a>
</span>
<br/>
</div>
</div>
So ultimately I would like to be able to target the filter.name.color and when it is this particular group have it display in this particular type of UI.
Any suggestions or links to readings is appreciated.
So based on your posted answer it looks like what you want to do is only show filters that have a particular name. If so, ngFilter should be able to take care of this like so:
| filter:{name: 'blah'}
(or {name: something} if the value is in a variable called something)
Full HTML:
<div heading="{{filter.name}}"
ng-repeat="filter in inventory.filters | filterOptions | orderBy:'name' | filter:{name:'blah'}"
is-open="true" show-attrs>
<h3>{{filter.name | uppercase}}</h3>
<div ng-repeat="option in filter.options">
<span ng-click="selectedFilter(filter, option.option, option.id)"><a>{{option.option}}{{option.count>0 ? "("+option.count +")": ""}}</a></span>
<br/>
</div>
<!--Then I just repeat each ng-if that I want to be available -->
</div>
If you want to filter based on filter.name.color, you can use | filter:{name.color: 'blue'}, but if having that dot in the object notation doesn't sit quite right with you, an alternate option is to use a custom filter function:
| filter:hasColor.bind(null, 'blue')
Then in your controller:
$scope.hasColor = function (color, filter) {
return filter.name && filter.name.color === color;
};
Ok, so what I tried was this and it seemed to get me some control over what I am showing and where:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div heading="{{filter.name}}"
ng-repeat="filter in inventory.filters | filterOptions | orderBy:'name'"
is-open="true" show-attrs>
<div ng-if="filter.name=='blah'" >
<h3>{{filter.name | uppercase}}</h3>
<div ng-repeat="option in filter.options">
<span ng-click="selectedFilter(filter, option.option, option.id)"><a>{{option.option}}{{option.count>0 ? "("+option.count +")": ""}}</a></span>
<br/>
</div>
</div>
<!--Then I just repeat each ng-if that I want to be available -->
</div>
So basically after the ng-repeat call within that div I am calling and nf-if and targeting the specific filter heading name/id to get only what I need to do.

Resources