checking the condition in ng-repeat - javascript

I am creating app in ionic /angularjs.
The controller fetches the data in JSON format from the URL and displays unique images in div elements. I want to allow these images to be clicked and then display the data according to offer_name, which is coming from the JSON data.
e.g.: Suppose I display the image for Amazon (in background offer_name is amazon (having 10 records)). When the user clicks on that, it displays all the records related to amazon.
Hope you get my point but no database is included; it only works with JSON data.
Also, how can the check current value be checked in ng-repeat?
Here is my code:
.controller('menuCtrl', function($scope,$http) {
$http.get("http://tools.vcommission.com/api/coupons.php?apikey=e159f64e3dd49fddc3bb21dcda70f10c6670ea91aac30c7cb1d4ed37b20c45b8").then(function (response) {
$scope.myData = response.data;
/* $scope.stack=[];
angular.forEach($scope.myData, function(item){
$scope.stack =item.store_image;
var uni_img=[];
for(var i=0 ; i< $scope.stack.length;i++)
{
if(uni_img.indexOf($scope.stack[i] == -1))
uni_img.push($scope.stack[i]);
}
console.log(uni_img);
})*/
});
$scope.dealopen = function($a){
for (var i=0;i<$scope.myData.length;i++)
{
//console.log($scope.data[i].name);
$link=$scope.data[i].offer_name;
if ($link==$a)
{
$window.open($link,"_self","location=yes");
console.log($a);
}
}
}
})
Html
<div class="item col-sm-2 col-sm-3 col-md-2 " ng-repeat="da in myData | unique: 'store_image'" >
<div class="thumbnail">
<img class="thumbnail img-responsive " ng-src="{{ da.store_image}}"
/>
<div class="caption">
<b class="group inner list-group-item-heading center-block">
{{da.offer_name | limitTo: 12 }} Deals</b>
<a class="item item-text-wrap" ng-href="#/Deals/{{da.offer_name}}">View Deal</a>
</div>
</div>
</div>
Here is the output:
.

One way to achieve this is to use ng-click to execute javascript (e.g. inline or call a function in the controller scope. Per the documentation for ngRepeat $index can be referenced for the current index:
Special properties are exposed on the local scope of each template instance, including:
+----------+---------+-----------------------------------------------------------------------------+
| Variable | Type | Details |
+----------+---------+-----------------------------------------------------------------------------+
| $index | number | iterator offset of the repeated element (0..length-1) |
| $first | boolean | true if the repeated element is first in the iterator. |
| $middle | boolean | true if the repeated element is between the first and last in the iterator. |
| $last | boolean | true if the repeated element is last in the iterator. |
| $even | boolean | true if the iterator position $index is even (otherwise false). |
| $odd | boolean | true if the iterator position $index is odd (otherwise false). |
+----------+---------+-----------------------------------------------------------------------------+
1
So the image tag can have the attribute ng-click to utilize that directive, like this:
<img class="thumbnail img-responsive " ng-src="{{ da.store_image}}" ng-click="showData(da.offer_name, $index)"/>
Then use Array.filter() to filter all offers into a filtered array of offers matching the offer_name:
$scope.showData = function (offer_name, index) {
$scope.offerName = da.offer_name;
$scope.filteredOffers = $scope.myData.filter(function(offer) {
return offer.offer_name == $scope.offerName;
});
}
And then add another set of elements to display the items in filteredOffers.
<div ng-repeat="offer in filteredOffers">
<div class="couponCode">{{offer.coupon_code}}</div>
<div class="couponTitle">{{offer.coupon_title}}</div>
<div class="couponDescription">{{offer.coupon_Description}}</div>
</div>
See the example below where the showData function updates the model selectedIndex, offerName and filteredOffers using these components.
angular.module('myApp', ['ui'])
.controller('menuCtrl', ['$scope', '$http',
function($scope, $http) {
$scope.offerName = ''; //set initially
$scope.selectedIndex = -1;
$scope.filteredOffers = [];
$http.get("http://tools.vcommission.com/api/coupons.php?apikey=e159f64e3dd49fddc3bb21dcda70f10c6670ea91aac30c7cb1d4ed37b20c45b8").then(function(response) {
$scope.myData = response.data;
});
$scope.showData = function(offer_name, index) {
$scope.offerName = offer_name;
$scope.filteredOffers = $scope.myData.filter(function(offer) {
return offer.offer_name == $scope.offerName;
});
$scope.selectedIndex = index;
}
}
]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js" data-semver="1.1.5" data-require="angular.js#*" context="anonymous"></script>
<script data-require="angular-ui#*" data-semver="0.4.0" src="//rawgithub.com/angular-ui/angular-ui/master/build/angular-ui.js" context="anonymous"></script>
<div ng-app="myApp" ng-controller="menuCtrl">
<div>
OfferName:
<span ng-bind="offerName"></span>
</div>
<div>
selected index:
<span ng-bind="selectedIndex"></span>
</div>
<div class="item col-sm-2 col-sm-3 col-md-2 " ng-repeat="da in myData | unique: 'store_image'">
<div class="thumbnail">
<img class="thumbnail img-responsive " ng-src="{{ da.store_image}}" ng-click="showData(da.offer_name, $index)" />
<div class="caption">
<b class="group inner list-group-item-heading center-block">
{{da.offer_name | limitTo: 12 }} Deals</b>
<a class="item item-text-wrap" ng-href="#/Deals/{{da.offer_name}}">View Deal</a>
</div>
</div>
</div>
<div ng-repeat="offer in filteredOffers">
<div class="couponCode">{{offer.coupon_code}}</div>
<div class="couponTitle">{{offer.coupon_title}}</div>
<div class="couponDescription">{{offer.coupon_Description}}</div>
</div>
</div>
1 https://docs.angularjs.org/api/ng/directive/ngRepeat

You can use $index, that is the variable used in agular to know the index position in ng-repeat, if you want to know more about another contro variables of ng-repeat read the docs in the next link https://docs.angularjs.org/api/ng/directive/ngRepeat
An basic example is.
CONTROLLER
app.controller('menuCtrl', function($scope,$http) {
$scope.myData = [{path:'http://www.imagefree1.com',info:'http://www.infoimage1.com'},
{path:'http://www.imagefree2.com',info:'http://www.infoimage2.com'},
{path:'http://www.imagefree3.com',info:'http://www.infoimage3.com'}];
$scope.callDetail=function(index)
window.open(myData[index].info);
})
HTML
<div ng-repeat="image in myData">
<a href="#" ng-click="callDetail($index)">
<img src="image.path" alt="Description"/>
</a>
</div>

At first look you never call the $scope.dealopen function,
may be this can work....
<div class="item col-sm-2 col-sm-3 col-md-2 " ng-repeat="da in myData | unique: 'store_image'" >
<div class="thumbnail">
<img class="thumbnail img-responsive " ng-src="{{ da.store_image}}"/>
<div class="caption">
<b class="group inner list-group-item-heading center-block">{{da.offer_name | limitTo: 12 }} Deals</b>
<a class="item item-text-wrap" ng-click="dealopen(da.offer_name)">View Deal</a>
</div>
</div>
</div>

Related

Update data in view when event happens

I have an Angular app that takes a large complex data set, and allows the user to filter it down using select lists. When data is filtered, a Google Map object is updated to display associated locations with the items that have been filtered.
I am trying to work it so that when the user clicks on a map pin, the filtered list of data is updated with only the items that are associated with that location.
Some snippets of the code:
$scope.showInfoWindow = function(event, site) {
var infowindow = new google.maps.InfoWindow();
var center = new google.maps.LatLng(site.Latitude, site.Longitude);
infowindow.setContent(
'<h3>' + site.SiteName + '</h3>' + '<p>' + site.Address1 + '<br/>' + site.Address2 + '<br/>' + site.City + ', ' + site.State + ' ' + site.ZipCode + '</p>');
infowindow.setPosition(center);
infowindow.open($scope.map);
$scope.findSelectedLocations(site.SiteName);
};
$scope.findSelectedLocations = function(SiteName) {
$scope.filteredData.forEach(function(itemElement, itemIndex) {
itemElement.Locations.forEach(function(locationElement, locationIndex) {
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if (siteElement.SiteName == SiteName) {
console.log('match!');
console.log('itemIndex: ' + itemIndex);
console.table(itemElement);
$scope.$apply(function() {
$scope.filteredData == itemElement;
});
return false;
}
});
});
});
<div class="trials-item-outer-wrapper">
<div class="trials-item-wrapper" du-scroll-container>
<!-- start of row -->
<div class="trials-item {{class}}" ng-repeat="data in (filteredData = (dataObject | byCountry : selectRegion | byRegion : selectState | byCity : selectCity | filterBy:['Phase']: selectPhase | filterBy:['Compound']: selectCompound | filterBy:['TherapeuticArea', 'TherapeuticArea_2',]: selectTherapy : 'strict' | unique: 'Id' | orderBy:'Phase' : reverse)) track by $index "
ng-class="{'open':$index == selectedRow}" id="anchor-{{$index}}">
<div class="trials-item-cell-wrapper">
<div class="trials-item-cell">
<img ng-click="toggleOpen($index, data.Compound,data.Number)" ng-src="assets/img/phase{{ data.Phase}}.png" width="54" height="61" alt="Phase {{ data.Phase}}" class="trials-item-phase-icon">
</div>
<div class="trials-item-cell"><a ng-click="toggleOpen($index, data.Compound,data.Number)"><span class="compound">{{ data.Compound }}</span><br/>{{ data.Compound_2 }}</a>
</div>
<div class="trials-item-cell">
<a href="" ng-click="toggleOpen($index, data.Compound,data.Number)">
<p class="trial-title">{{ data.TitleShort }}</p>
<p>{{ data.Number }} {{ data.Status }}</p>
</a>
</div>
<div class="trials-item-cell">
<a href="" ng-click="toggleOpen($index, data.Compound,data.Number)">
{{ data.TherapeuticArea }}<span ng-if="data.TherapeuticArea_2">, {{ data.TherapeuticArea_2 }}</span>
</a>
</div>
<div class="trials-item-cell location-cell">
<span ng-if="data.Disclaimer">
<p>{{data.Disclaimer}}</p></span>
</div>
<div class="trials-item-cell cart-actions">
<div ng-if="!isInCart(data.Id)" class="add-to-cart">
<a href="" ng-click="addToCartModalOpen($index, data, data.Id)">
<img src="assets/img/cart-add.png" width="73" height="65" alt="Cart Add">
<span>Add to Cart</span>
</a>
</div>
<div ng-if="isInCart(data.Id)" class="remove-from-cart">
<a href="" ng-click="removeFromCart(data.Id)">
<img src="assets/img/cart-added.png" width="73" height="65" alt="Cart Add">
<span>Remove from Cart</span>
</a>
</div>
</div>
<div class="trials-item-cell">
<a ng-click="toggleOpen($index, data.Compound,data.Number)">
<p class="more-text"></p>
<div class="more glyphicon"></div>
</a>
</div>
</div>
<!-- trials-item-cell-wrapper -->
<div class="trials-tabs" ng-include="data.Url"></div>
</div>
<!-- end of ng-repeat -->
So the view uses the $scope.filteredData obj to display the list of filtered data. In $scope.showInfoWindow, I'm displaying an infowindow for a map pin that the user clicks on. I then pass the 'site.SiteName' value to the $scope.findSelectedLocations method to loop thru the $scope.filteredData object to find any matches to that location. This part works fine. I can console.table the data and see that itemElement is indeed showing the correct data when the map pin is click (via $scope.showInfoWindow() ).
When I'm having the issue is getting that updated data back in to the view.
In $scope.findSelectedLocations, I'm updating $scope.filteredData with the updated items in itemElement, but the view that displays $scope.filteredData isn't updating. As you can see below, I've tried wrapping that assignment in a $scope.$apply, but that doesn't work either.
No need for apply(), that's needed when something out of Angular's context needs to be rendered explicitly in a digest cycle.
May be there's a typo:
Instead of:
$scope.filteredData == itemElement;
Use:
$scope.filteredData = itemElement;
And try now.
Angular has two-way data binding. So whenever your model updates, views will automatically be get rendered. Nothing needs to be done explicitly. We have to have a watcher if we want to update the view/logic based on some change detection.

Filtering and Sorting in Ionic Service Factory

sorry for newbie question. I want to add filtering and sorting by name to my page. When i try using this code it is still work when i am using list of items from variable in controller scope but after i am using factory in services.js, there is two problem:
When i am typing the search word in search box, filter is work and only show the filtered item but i can't clear the filter again (when i am deleting the search word with backspace the item is still filtered)
The order by doesn't work anymore for sorting the items
Here is the code :
(HTML)
<ion-view view-title="Foods">
<ion-content class="padding">
<div class="bar bar-header item-input-inset">
<label class="item-input-wrapper">
<i class="icon ion-ios-search placeholder-icon"></i>
<input type="search" placeholder="Search" ng-model="foodSearch.search">
</label>
</div>
<button class="button button-block button-energized" ng-click="showOrderOptions()">
Order by
</button>
<div class="list ">
<a class="item" href="#" ng-hide="isOrderOptionsHide" ng-click="reverse=!reverse;order('name',reverse)">
Name
</a>
<a class="item" href="#" ng-hide="isOrderOptionsHide" ng-click="reverse=!reverse;order('rating',reverse)">
Rating
</a>
</div>
<ion-list>
<ion-item class="list card" ng-repeat="food in foods = (foods | filter: filterFood)"
href="#/tab/foods/{{food.id}}">
<div class="item item-head">
<h2 style="text-align:center;"><b>{{food.name}}</b></h2>
<div class="row">
<div class="col item item-image" style="width:100px;height:100px;">
<img class="" src="{{food.imageSrc}}" >
</div>
<div class="col item item-image">
<h2>{{food.title}}</h2>
<div class="row">
<img src="img/smile.jpg" style="width:100%; height:100%; margin-top: -10px;"class="col col-40">
<h3 class="col col-60" >{{food.rating}}</h3>
</div>
</div>
</div>
</div>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
(Controller.js):
.controller('FoodsCtrl', function($scope,Foods,$filter) {
$scope.foods = Foods.all();
$scope.remove = function(food) {
Foods.remove(food);
};
$scope.foodSearch = {search: ''};
$scope.filterFood = function (item){
return item.title.toLowerCase().indexOf($scope.foodSearch.search.toLowerCase()) >= 0
|| item.name.toLowerCase().indexOf($scope.foodSearch.search.toLowerCase()) >= 0;
}
$scope.isOrderOptionsHide = true;
$scope.reverse=true;
$scope.showOrderOptions = function (){
$scope.isOrderOptionsHide = !$scope.isOrderOptionsHide;
}
var orderBy = $filter('orderBy');
$scope.order = function(predicate, reverse) {
$scope.foods = orderBy($scope.foods, predicate, reverse);
$scope.isOrderOptionsHide = true;
};
})
Just do this way ng-repeat="food in foods | filter: foodSearch.search | orderBy: 'name'" You do not have to do this :
$scope.filterFood = function (item){
return item.title.toLowerCase().indexOf($scope.foodSearch.search.toLowerCase())..
angular filter automaticaly does that.

AngularJS, problems with $index variable in ng-repeat

I'm trying to fill out a 2 column table in AngularJS. I'm using ng-repeat directive to fill out the table, but it's not's working the way I'm planning. My $scope.items is: [Coors, Jameson, Bacardi, Corona]
I want the table to look like this:
| Coors (0) | Jameson (1) |
| Bacardi (2) | Corona (3) |
however, it looks like this:
| Coors (0) | Coors (1) |
| Bacardi (2) | Bacardi (3) |
I'm confused as to why the [$index+1] directive in the my script is only working in the actual text portion of the script (in parenthesis), while the <item-card> div does not seem to properly displaying items[$index+1], and instead is displaying items[$index]. Here is my script:
<div class=row ng-repeat="item in items" ng-if="$index %2 ==0">
<div class="col col-50" ng-if="$index < items.length">
<item-card item="{{item[$index]}}"></item-card>
({{$index}})
</div>
<div class="col col-50" ng-if="$index +1 < items.length">
<item-card item="{{items[$index+1]}}"></item-card>
({{$index+1}})
</div>
</div>
Does anyone know why this might not be working as intended?
Edit: Including is itemcard.html.
<div class = "card" >
<img id = "cardImage" ng-src= "data:image/jpeg;base64,{{item.image}}" width = "100%"/>
{{item.cartQuantity}}
<cardHeader>{{item.itemName}}</cardHeader><br>
<cardHeader ng-if= "item.paksize >1">{{item.paksize}} pack</cardHeader>
<button class="button" ng-click="addToCart(item)">+</button>
<button class="button" ng-click="decrementCart(item)">-</button>
</div>
What you're trying to do seems a little odd to me. Rather than trying to split the array of items into even chunks of 2 columns with Directive Fu, might you consider using lodash.chunk?
<script>
angular.module('example', [ ])
.run(function($scope){
$scope.items = _.chunk([ /* . . . */ ], 2);
});
</script>
<div ng-app="example">
<div class=row ng-repeat="chunk in items">
<div class="col col-50">
<item-card item="{{chunk[0]}}"></item-card>
({{$index}})
</div>
<div class="col col-50">
<item-card item="{{chunk[1]}}"></item-card>
({{$index+1}})
</div>
</div>
</div>
If you wanted to be really Angular about it (a pun!), you could register lodash.chunk as a custom Filter instead:
<script>
angular.module('example', [ ])
.run(function($scope){
$scope.items = [ /* . . . */ ];
})
.filter('chunk', function(){
return _.chunk;
});
</script>
<div ng-app="example">
<div class=row ng-repeat="chunk in items | chunk:2">
<div class="col col-50">
<item-card item="{{chunk[0]}}"></item-card>
({{$index}})
</div>
<div class="col col-50">
<item-card item="{{chunk[1]}}"></item-card>
({{$index+1}})
</div>
</div>
</div>

Simple previous\next slider using angular

I have a web page which displays a list of items, the number of items can get quite big so I would like to display only 3 at a time and have next\previous buttons which let the user navigate between items.
I'm very new to Angular but I managed to retrieve all the items and display them on the UI but have no idea where to start to only display three and wire up the next and previous buttons to enable navigation.
Here's my code:
JS:
var app = angular.module('myApp', []);
app.controller('servicesController', function ($scope, $http) {
$http.get(url + "api/MapServiceAPI/GetServers")
.success(function (response) {
$scope.servers = response.Result;
});
});
HTML:
<div class="row top-space" ng-app="myApp" ng-controller="servicesController">
<div class="pull-left">
<img src="~/Content/Images/Service/PREVIOUS.png" />
<h4>PREVIOUS</h4>
</div>
<div class="pull-right">
<img src="~/Content/Images/Service/NEXT.png" />
<h4>NEXT</h4>
</div>
<ul class="col-md-3 text-center" ng-repeat="s in servers" ng-click="serviceClick(s.ServiceId)">
<li>
<div class="container">
<h4>{{ s.ServerName }}</h4>
</div>
<div class="container">
<img src="~/Content/Images/Server/SERVER.png" />
</div>
<div class="container">
<h5>{{ s.ServerDescription }}</h5>
</div>
</li>
</ul>
</div>
you can achieve using filters limitTo property
> <li ng-repeat="datalist in datalists | pagination: curPage * pageSize
> | limitTo: pageSize">
refere this jsfiddle which help you to understand better.
http://jsfiddle.net/dulcedilip/x7tg15v9/

Give a value to an ng-model="searchText" input based on list item clicked in Angular JS

I created a list that is searchable with an input using angular.js (ng-model="searchText"). On click of the list elements you can pull the content of the selected item using {{selected | json}}. I want to apply this selected element as the value of the input when a list item is clicked.
I essentially want to create my own autocomplete that always displays a list of options, filters options while typing, and fills in the input on click of an option.
HTML
<html ng-app>
<section>
<div id="content-body" class="container search-page"><!-- begin content-body -->
<div id="content-frame" class="container"></div><!-- end content-frame -->
<section>
<div class="search-container">
<div class="search-wrapper">
<input type="search" class="input-from" autocomplete="off" placeholder="Search" ng-model="searchText" value="{{searchText}}">
</div>
</div>
</section>
<section>
<div ng-controller="ContentCtrl">
<ul class="list-group search">
<!--<li class="list-group-item group-title">
<span class="icon itinerary-icon"></span>
Popular Destinations
</li>-->
<a ng-click="setMaster(cities)" ng-repeat="city in cities | filter:searchText | limitTo:limit" href="#" class="list-group-item">{{city}}</a>
</ul>
</div>
</section>
</div><!-- end content-body -->
</html>
JS
function ContentCtrl($scope, $http) {
"use strict";
$scope.url = '../mobile-site/cities.json';
$scope.cities = [];
$scope.limit = 10; // max 10 cities loaded
$scope.fetchContent = function() {
$http.get($scope.url).then(function(response){
$scope.cities = response.data.cities;
});
}
$scope.fetchContent(); // build cities list
$scope.setMaster = function(city) {
$scope.searchText = city; // pull selected city using {{selected | json}}
}
}
JSON
{
"version": "082B6AF45261B81358E8F99F0FAEC4A4",
"cities": [
"A Friela Maside, Spain",
"A Gudina, Spain",
"AHA, Germany",
"AL, Norway"
]
}
I think you have a few mistakes in the code:
<div ng-model="chosen">
<a ng-click="setMaster(cities)" ng-repeat="cities in cities | filter:searchText | limitTo:limit" href="#" class="list-group-item">{{cities}}</a>
</div>
shoud be
<div ng-repeat="city in cities | filter:searchText | limitTo:limit">
<a ng-click="setMaster(city)" class="list-group-item">{{city}}</a>
</div>
then I think what you want is
$scope.setMaster = function(city) {
$scope.searchText = city;
}
Also, I'm not sure what the ng-model on the div is for, as far as I know it is used only for inputs, textareas and selects. See http://docs.angularjs.org/api/ng.directive:ngModel.
You probably want something like this fiddle -> http://jsfiddle.net/weSpW/3/.

Categories