Make ng-repeat call a function again on model change - angularjs

I have a table with an ng-repeat over a function that I want to be rerendered after a user logs in. How do I make a view load the ng-repeat and again to triger the function. Is there a way to make an ng-repeat rerender on a change in the model?
Here is the view, to give an idea why a function is used instead of just looping over a model. The repeat in question is ng-repeat="(index, event) in vm.getEvents(dayObject) track by $index" :
<!-- CALENDAR NAV -->
<div class="calendar-nav">
<div class="prev">
<button class="btn btn-default pull-right" ng-click="vm.goToPrevWeek()" ng-disabled="vm.isCurrentWeek"><i class="glyphicon glyphicon-chevron-left"></i></button>
</div>
<div class="date">
<p class="text-primary text-center">{{vm.weekViewString}}</p>
</div>
<div class="next">
<button class="btn btn-default pull-left" ng-click="vm.goToNextWeek()"><i class="glyphicon glyphicon-chevron-right"></i></button>
</div>
</div>
<!-- END CALENDAR NAV -->
<!-- CALENDAR HEADER -->
<div class="calendar-header">
<div class="weekdate-header date-header day-1 split-{{vm.weekSplit}}" ng-class="{'today': dayObject.isToday}" ng-repeat="(index, dayObject) in vm.calendarDays track by $index">
<div class="date-container"><span class="date">{{dayObject.day}}</span><span class="week-day"> {{dayObject.weekDay}}</span></div>
</div>
</div>
<!-- END CALENDAR HEADER -->
<!-- CALENDAR CONTENT -->
<div class="calendar-content">
<div class="calendar-aside">
<div class="day-hour" ng-repeat="(index, hourObject) in vm.calendarHours track by $index">
<span class="hour">{{hourObject.hour}}</span>
</div>
</div>
<div class="calendar-days">
<div class="calendar-day day-col day-1 split-{{vm.weekSplit}}" ng-class="{'today': dayObject.isToday}" ng-repeat="(index, dayObject) in vm.calendarDays track by $index">
<div class="mobile-day hidden-lg hidden-md hidden-sm">
<div class="date-container"><span class="date">{{dayObject.day}}</span><span class="week-day"> {{dayObject.weekDay}}</span></div>
</div>
<div class="day-hour hour-{{hourObject.number}}" ng-repeat="(index, hourObject) in vm.calendarHours track by $index">
<div class="hour">
<div class="half-hour"></div>
</div>
</div>
<!-- CALENDAR EVENTS -->
<div id="{{event.idName}}" class="event-container {{event.type}}" style="top: {{event.top}}px; left: {{event.left}}%; width: {{event.width}}%; height: {{event.height}}px;"
ng-repeat="(index, event) in vm.getEvents(dayObject) track by $index" ng-switch="event.type">
<div class="buttons" ng-switch-when="">
<div class="amount">{{event.spotsAvailable}}</div>
</div>
<div class="buttons" ng-switch-when="success">
<i class="glyphicon glyphicon-ok-sign"></i>
</div>
<div class="buttons" ng-switch-when="full">
<i class="glyphicon glyphicon-ban-circle"></i>
</div>
<div class="text">
<span class="title">{{event.name}}</span>
<p class="locatie-time hidden-lg hidden-md hidden-sm"> <span>{{event.startsAt | date:'HH:mm' }}</span> - <span>{{event.endsAt | date:'HH:mm' }}</span> </p>
<span class="locatie-info">{{event.formattedAddress}}</span>
</div>
</div>
<!-- END CALENDAR EVENTS -->
</div>
</div>
</div>
<!-- END CALENDAR CONTENT -->

I ended up replacing the function in the ng-repeat with a direct link to the data the function was returning and now the view is updating.

Related

Bootstrap carousel in ng-repeat

I have problem with Bootstrap carousel in ng-repeat, because images are not load one by one if carousel changes, but all images are load all at onece. I found similar questions in stackoverflow, but in my case I loading data from database (not use $scope)
<div class="container">
<div class="carousel slide" id="myCarousel">
<div class="carousel-inner">
<div class="item active">
<div class="row">
<div class="col-xs-3" ng-repeat="product in main.products"><img ng-src="../../uploads/{{ product.imagePath }}" class="img-responsive"></div>
</div>
</div>
<div class="item">
<div class="row">
<div class="col-xs-3" ng-repeat="product in main.products"><img ng-src="../../uploads/{{ product.imagePath }}" class="img-responsive"></div>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" data-slide="prev"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="right carousel-control" href="#myCarousel" data-slide="next"><i class="glyphicon glyphicon-chevron-right"></i></a>
</div>
</div>
The issue is that you are repeating all of your images inside an item of the carousel. A carousel item is defined by the "item" class. If you want a single image to displayed at once then repeat the items like so:
<div class="container">
<div class="carousel slide" id="myCarousel">
<div class="carousel-inner">
<!-- add the `active` class to the first item with one-time binding (if $index is 0) -->
<div class="item {{::($index === 0 ? 'active' : '')}}" ng-repeat="product in main.products track by $index">
<div class="row">
<div class="col-xs-3"><img ng-src="../../uploads/{{ product.imagePath }}" class="img-responsive"></div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" data-slide="prev"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="right carousel-control" href="#myCarousel" data-slide="next"><i class="glyphicon glyphicon-chevron-right"></i></a>
</div>
</div>
</div>

Ionic / AngularJS key not accessible in ng-repeat

I am trying to access the {{key}} from an ng-repeat from a controller using Ionic 1. The {{key}} that is generated as text is different from the {{key}} I am receiving at the controller, not sure why this is.
What I want to do is find the div id which should be dynamically generated using the id = "historyHeader_{{key}}" and need to receive it using ng-click="loadInlineHistory({{key}})"
Controller:
$scope.loadInlineHistory = function (dateLoaded) {
var textS = $("#historyHeader_"+dateLoaded).text();
}
View
<ion-list>
<div ng-repeat="(key, value) in history | groupBy: 'date'"" style="background:#fff;padding:0.4em">
<div class="item item-divider">
<span style="min-height: 100%" id="historyHeader_{{key}}"> {{key}}</span>
</div>
<div style="width: 100%">
<div class="row" ng-repeat="hist in value">
<div ng-click="testRepeatx()">
<div class="row">
<div class="col col-50" align="left">3 laterals </div>
<div class="col col-50" align="left" style="color:#999">{{hist.reps}} calories</div>
</div>
</div>
</div>
<div class="row" >
<button class="button button-block button-balanced" ng-click="loadInlineHistory({{key}})"> <i class="ion-plus"></i></button>
</div>
</div>
</div>
</ion-list>
Just remove the curly brackets from the ng-click function call.
<div class="row" >
<button class="button button-block button-balanced"
ng-click="loadInlineHistory(key)"> <i class="ion-plus"></i></button>
</div>

Re-initializing Angular-slick directive

I am using the Angular-slick directive and I am having a tiny bit of a problem. I am sure that others may have had similar problems, but I hope someone out there can help me figure this out.
So I have a series of angular directives on my page. Each directive has properties that can be set in order to filter data in the other directives. My Angular-slick directive is bound to data that is coming from a Web API call. On the first load, the directive is perfect and it works fine. But once an action from one of the other directives causes the Angular-slick directive to filter its data (which is just another Web API call that returns similar data as the initial load), the entire the slider gets wacky and out of order. All the slides are displayed vertically.
Here is the code from the template:
<div id="slickContainer" ng-show="ctlr.SectionDataAvailable">
<div id="slickSlider">
<div id="currentDateRange">
<span ng-bind="ctlr.ApiResult.CurrentDateRangeHeaderText"></span>
</div>
<div id="previousDateRange">
<span ng-bind="ctlr.ApiResult.PreviousDateRangeHeaderText"></span>
</div>
<div id="slick">
<slick init-onload="false"
data="ctlr.DataLoaded"
arrows="true"
slides-to-show="3"
slides-to-scroll="3"
infinite="false"
dots="false"
responsive="ctlr.SlickResponsive()">
<div ng-repeat="doubledUpResult in ctlr.ApiResult.DoubledUpResults" id="slickConatiner">
<!--Current Item-->
<div id="currentItemContainer">
<div class="creative-item-heading-container"
ng-show="doubledUpResult.CurrentItem.HasACreative">
<span>{{doubledUpResult.CurrentItem.Headline}}</span><br />
<div ng-show="doubledUpResult.CurrentItem.IsFirstOccurrenceVisible">
<span style="color: #dd4f04;">First Occurrence: </span>
<span>{{doubledUpResult.CurrentItem.FirstPropertyName}}</span>
<span>{{doubledUpResult.CurrentItem.FirstCreativeDateText}}</span>
</div>
<div ng-show="doubledUpResult.CurrentItem.IsLastOccurrenceVisible">
<span style="color: #dd4f04;">Last Occurrence: </span>
<span>{{doubledUpResult.CurrentItem.LastPropertyName}}</span>
<span>{{doubledUpResult.CurrentItem.LastCreativeDateText}}</span>
</div>
<div ng-show="doubledUpResult.CurrentItem.HasACreative">
<span style="color: #dd4f04;">Total: </span>
<span>
{{doubledUpResult.CurrentItem.ActivityTotalText}}{{doubledUpResult.CurrentItem.ActivityFootnoteIndicator}}
</span>
</div>
<div ng-show="doubledUpResult.CurrentItem.IsAdvertiserVisible">
<span style="color: #dd4f04;">{{doubledUpResult.CurrentItem.EntityTypeDescription}}:</span>
<span>
<a ng-click="ctlr.OnEntityLinkClicked(doubledUpResult.CurrentItem)">
{{doubledUpResult.CurrentItem.EntityName}}
</a>
</span>
<span>{{doubledUpResult.CurrentItem.ExtraAdvertiserNote}}</span>
</div>
</div>
<div class="creative-thumbnail"
ng-show="doubledUpResult.CurrentItem.HasACreative">
<kmi-crv-thumbnail creative-id="doubledUpResult.CurrentItem.CreativeIdStr"
creative-type="doubledUpResult.CurrentItem.CreativeType"
size="ctlr.ThumbnailSize"
storage-provider="ctlr.StorageProvider"
base-path="'/KMI/IntelliDrive/ApplUI'"
style="margin: 0 auto; cursor:pointer;"
ng-click="ctlr.OnCreativeClicked(doubledUpResult.CurrentItem)"
is-delayed="'true'"></kmi-crv-thumbnail>
</div>
<div class="creative-item-button-container"
ng-show="doubledUpResult.CurrentItem.HasACreative">
<a ng-click="ctlr.OnCreativeClicked(doubledUpResult.CurrentItem)"
class="top-creatives-button current-item"
ng-show="doubledUpResult.CurrentItem.IsQuickViewVisible"
ng-style="ctlr.GetStyle(doubledUpResult.CurrentItem, 'QuickView')">Quick View</a>
<a ng-click="ctlr.OnViewInLibraryClicked(doubledUpResult.CurrentItem)"
class="top-creatives-button current-item"
ng-show="doubledUpResult.CurrentItem.CanViewInLibrary"
ng-style="ctlr.GetStyle(doubledUpResult.CurrentItem, 'ViewInLibrary')">View in Library</a>
<a ng-click="ctlr.OnAddToCartClicked(doubledUpResult.CurrentItem)"
class="top-creatives-button current-item"
ng-show="doubledUpResult.CurrentItem.CanAddToShoppingCart"
ng-style="ctlr.GetStyle(doubledUpResult.CurrentItem, 'AddToCart')">Add to Cart</a>
</div>
</div>
<!--Previous Item-->
<div id="previousItemContainer">
<div class="creative-item-heading-container"
ng-show="doubledUpResult.PreviousItem.HasACreative">
<span>{{doubledUpResult.PreviousItem.Headline}}</span><br />
<div ng-show="doubledUpResult.PreviousItem.IsFirstOccurrenceVisible">
<span style="color: #dd4f04;">First Occurrence: </span>
<span>{{doubledUpResult.PreviousItem.FirstPropertyName}}</span>
<span>{{doubledUpResult.PreviousItem.FirstCreativeDateText}}</span>
</div>
<div ng-show="doubledUpResult.PreviousItem.IsLastOccurrenceVisible">
<span style="color: #dd4f04;">Last Occurrence: </span>
<span>{{doubledUpResult.PreviousItem.LastPropertyName}}</span>
<span>{{doubledUpResult.PreviousItem.LastCreativeDateText}}</span>
</div>
<div ng-show="doubledUpResult.PreviousItem.HasACreative">
<span style="color: #dd4f04;">Total: </span>
<span>
{{doubledUpResult.PreviousItem.ActivityTotalText}}{{doubledUpResult.PreviousItem.ActivityFootnoteIndicator}}
</span>
</div>
<div ng-show="doubledUpResult.PreviousItem.IsAdvertiserVisible">
<span style="color: #dd4f04;">{{doubledUpResult.PreviousItem.EntityTypeDescription}}:</span>
<span>
<a ng-click="ctlr.OnEntityLinkClicked(doubledUpResult.PreviousItem)">
{{doubledUpResult.PreviousItem.EntityName}}
</a>
</span>
<span>{{doubledUpResult.PreviousItem.ExtraAdvertiserNote}}</span>
</div>
</div>
<div class="creative-thumbnail"
ng-show="doubledUpResult.PreviousItem.HasACreative">
<kmi-crv-thumbnail creative-id="doubledUpResult.PreviousItem.CreativeIdStr"
creative-type="doubledUpResult.PreviousItem.CreativeType"
size="ctlr.ThumbnailSize"
storage-provider="ctlr.StorageProvider"
base-path="'/KMI/IntelliDrive/ApplUI'"
ng-click="ctlr.OnCreativeClicked(doubledUpResult.PreviousItem)"
style="margin: 0 auto; cursor:pointer;"
is-delayed="'true'"></kmi-crv-thumbnail>
</div>
<div class="creative-item-button-container"
ng-show="doubledUpResult.PreviousItem.HasACreative">
<a ng-click="ctlr.OnCreativeClicked(doubledUpResult.PreviousItem)"
class="top-creatives-button previous-item"
ng-show="doubledUpResult.PreviousItem.IsQuickViewVisible"
ng-style="ctlr.GetStyle(doubledUpResult.PreviousItem, 'QuickView')">Quick View</a>
<a ng-click="ctlr.OnViewInLibraryClicked(doubledUpResult.PreviousItem)"
class="top-creatives-button previous-item"
ng-show="doubledUpResult.PreviousItem.CanViewInLibrary"
ng-style="ctlr.GetStyle(doubledUpResult.PreviousItem, 'ViewInLibrary')">View in Library</a>
<a ng-click="ctlr.OnAddToCartClicked(doubledUpResult.PreviousItem)"
class="top-creatives-button previous-item"
ng-show="doubledUpResult.PreviousItem.CanAddToShoppingCart"
ng-style="ctlr.GetStyle(doubledUpResult.PreviousItem, 'AddToCart')">Add to Cart</a>
</div>
</div>
</div>
</slick>
</div>
</div>
</div>
When the action from another directive is fired, all I want to do is make a Web API call, which brings back a new data set that the slider is then rebound to. My problem is I can't figure out how to do the rebinding without breaking the slider.
Thanks.

avoid modal images loading before being clicked

Problem Description:
I have an e-commerce application, in which I have to load a lot of product images. We used 200*200 images for small images, but there are modals which are 600*600 in size and appear when clicked on any product.
The problem is, when each page is loaded, all the images (200*200 and 600*600) are getting loaded, which is making the application too slow.
Question: Is there any way to avoid the (600*600) images to load before being clicked. I would like the application to load only the 200*200 images initially and load any 600*600 image on request.
Technology: (Jade, Angularjs, Nodejs)
Code:
<div ng-repeat="product in category.products | filter:query | orderBy: 'productName'">
<div class="panel-default panel thumbnail" id="imgs">
<div class="panel-body">
<a href="#" data-target="#img_modal{{product._id}}" data-toggle="modal">
<img class="img-responsive center-block" ng-src="{{product.productImage_tn}}" alt="" id="items" />
</a>
<div class="modal" id='img_modal{{product._id}}' tabindex='-1' role='dialog' area-hidden='true'>
<div class="modal-dialog" style="width: 630px;">
<div class="modal-content">
<div class="modal-header">
<h4>{{ product.productName }}
<button class="close" type='button' data-dismiss='modal' area-hidden='true'> ×</button>
</h4>
</div>
<div class="modal-body">
<img ng-src="{{product.productImage_600}}" style=" position: relative; height: 400px;" class="img-responsive center-block">
</div>
<div class="modal-footer">
<div class="row">
<div class="col-sm-4 col-md-4">
<h4>$ {{ product.productPrice }} {{ product.productUnit }}</h4>
</div>
<div class="col-sm-2 col-md-2"></div>
<div class="col-sm-6 col-md-6">
<div class="input-group number-spinner">
<span class="input-group-btn">
<button class="btn btn-default" ng-click="removeItem(product._id)">
<span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<label class="form-control text-center">{{ getItemQty(product._id) }}</label>
<span class="input-group-btn">
<button class="btn btn-default" ng-click="addItem(product._id)">
<span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel-footer" id="panelfooter">
<h6>{{ product.productName }} </h6>
<h6>$ {{ product.productPrice }} {{ product.productUnit }}</h6>
</div>
<div class="input-group number-spinner">
<span class="input-group-btn">
<button class="btn btn-default" ng-click="removeItem(product._id)">
<span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<label class="form-control text-center">{{ getItemQty(product._id) }}</label>
<span class="input-group-btn">
<button class="btn btn-default" ng-click="addItem(product._id)">
<span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
</div>
</div>
Look at ui-bootstrap and the example for Modal over there. The reason you see all images being loaded is that you have inlined all your content. What you should do is put the modal content in a separate template and use the ng-click directive to open the modal dialog. Using the templateUrl option will ensure that content is loaded when clicked and not before

How do I use AngularJS to bind to a span that uses Livestamp?

I would like to use Angular data-binding to dynamically change the date used for Livestamp.
For instance, I would like to make the following dynamic:
<span data-livestamp="1413704094"></span>
by using Angular databinding, something like:
<span data-livestamp="{{item.Date.toISOString}}"></span>
How do I do it? The above code doesn't work.
EDIT:
Here's how it's used:
<div class="panel panel-default messageItems" ng-repeat="item in vm.itemsTop | orderBy:'Id':true" ng-animate="'animate'">
<div class="panel-body">
<div class="media">
<a class="pull-left" href="/People/{{item.User.Username}}">
<img class="media-object"
src="http://mysite/{{item.User.Username}})/avatar"
alt="{{item.User.Username}}" />
</a>
<div class="media-body">
<h4 class="media-heading">
<span ng-bind="item.User.Username"></span>
</h4>
<h6>
posted <span data-livestamp="{{item.Posted.toISOString}}"></span> (<span ng-bind="item.Posted.toUTCString()"></span>)
</h6>
<p class="emojstext">
<span ng-bind="item.Text"></span>
</p>
</div>
</div>
</div>

Resources