I'm new to Angular and I'm trying to pass a variable into the filter but I'm having no luck. It works as intended when I hard code the value but it doesn't seem to be accepting the value.
JS
var app = angular.module('footballApp', []);
app.controller("TeamCtrl", function($scope, $http){
$http.get("clubs.php/teams").success(function (data){
$scope.teams = data.team;
}).error(function (){
alert("an error has occured");
});
$http.get("players.php/players").success(function (data){
$scope.players = data.player;
console.log($scope.players);
}).error(function (){
alert("an error has occured");
});
});
HTML
<script type="text/ng-template" id="team-single.html">
<div class="team-box">
<div class="badge">
<img src="logo.png" width="100" height="100"></div>
<div class="team-name">{{x.club_name}}</div>
<p><b>Club Manager:</b> {{x.club_manager}}</p>
<p><b>Ground:</b> {{x.club_ground}}</p>
<p><b>Nickname:</b> {{x.club_nickname}}</p>
<div class="team-p">{{x.club_info}}</div>
<div class="key-players">
Key Players
</div>
<div class="players">
<ul class="player-list">
<li ng-repeat="player in players | filter: { club_name: '{{player.club_name}}' }" data-toggle="modal" data-target="#{{player.id}}">{{player.player_name}}</li>
</ul>
</div>
</div>
</script>
<div class="row teams" ng-controller="TeamCtrl">
<div class="container">
<div class="col-md-4" ng-repeat="x in teams" ng-include="'team-single.html'"></div>
</div>
</div>
Everything works fine apart from the part where I use ng-repeat with a filter to filter the list that shows by club_name. Can anyone tell me where I'm going wrong?
The variable doesn't need to be in curly braces.
<ul class="player-list">
<li ng-repeat="player in players | filter: { club_name: player.club_name }" data-toggle="modal" data-target="#{{player.id}}">{{player.player_name}}</li>
</ul>
e.g. player.club_name instead of '{{player.club_name}}'
Related
Sorry for the basic question, extremely new to software development and angular in particular. I'm currently making a small app that uses an api to find cinemas near a certain postcode.
I have made a results page that show what films are playing in a certain cinema, but I want to limit the amount of results returned and include a 'Show more films' button.
I have included my html and controller below:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in $ctrl.listings">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in listing.times">{{time}}</li>
</ul>
</div>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
ListingsController
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}
Could I just use limitTo to achieve this?
P.S sorry for the poor information, it's my first question on here.
Please try the following example in the fiddle link -
Using the limitTo filter.
ng-repeat="d in data | limitTo: limitvar"
https://jsfiddle.net/m0q9ju8a/
let me know if this helps.
You can do like this:
HTML
<div class="main-container">
<fountain-header></fountain-header>
<div class="cinemas-container">
<h2 align="center" class="cinemas-h2">Movies playing here:</h2>
<div class="cinema2" ng-repeat="listing in vm.listings | limitTo: vm.limit as results">
<h3 class="cinema-h5">{{listing.title}}</h3>
<ul class="cinema-h4">
<li ng-repeat="time in vm.listing.times">{{time}}</li>
</ul>
</div>
<button ng-hide="results.length === vm.listings.length" ng-click="vm.limit = vm.limit +8">show more...</button>
<div class="main-container">
</main>
</div>
<fountain-footer></fountain-footer>
</div>
</div>
and in youn controller
function ListingsController($http, $stateParams) {
console.log($stateParams);
console.log($stateParams.cinemaID);
var vm = this;
vm.limit = 8;
$http
.get('https://api.cinelist.co.uk/get/times/cinema/' + $stateParams.CinemaID +'?day=1')
.then(function (response) {
console.log(response);
vm.listings = response.data.listings;
});
}
I have two AngularJS apps in one page, I was wondering why the Angular was breaking then realised it was probably because both apps are name the same thing (I'm very new to AngularJS).
What I need to know if what I need to change to differentiate between them if this makes sense.
This is my code with the two apps in separate divs NorthWest and NorthEast.
If anyone could help me with this I would be very grateful,
Thanks, in advance!
<div id="NorthWest" class="desc">
<script>
var app = angular.module('myApp', []);
app.controller('regionsLinks', function($scope, $http) {
var url = 'http://scd.blaze.wpengine.com/wp-json/posts?type=listings&filter[listing_area]=northwest';
$http.get(url).then(function (data) {
$scope.data = data.data;
});});
app.controller('regionsLinks1', function($scope, $http) {
var url = 'http://scd.blaze.wpengine.com/wp-json/posts?type=listings&filter[listing_area]=northeast';
$http.get(url).then(function (data) {
$scope.data = data.data;
});});
</script>
<div ng-app="myApp">
<div ng-controller="regionsLinks">
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<img src="{{d.acf.logo}}">
<div id="listing-contact">Contact: {{d.acf.contact}}, {{d.acf.position}}</div>
<div id="listing-address-1">
{{d.acf.address_1}},
{{d.acf.address_2}}
{{d.acf.address_3}}
{{d.acf.town}}
{{d.acf.county}}
{{d.acf.postcode}}
</div>
<div id="listing-phone">Telephone: {{d.acf.telephone}}</div>
<div id="listing-mobile">Mobile: {{d.acf.mobile}}</div>
<div id="listing-email">Email: {{d.acf.email}}</div>
<div id="listing-website">Website: {{d.acf.website}}</div>
<div id="listing-established">Established: {{d.acf.established}}</div>
<div id="listing-about">About: {{d.acf.about}}</div>
<div id="listing-mailingaddress">
Mailing Address: {{d.acf.mailing_address_}}, {{d.acf.mailing_address_2}},
{{d.acf.mailing_address_3}}, {{d.acf.mailing_town}}, {{d.acf.mailing_county}}, {{d.acf.mailing_postcode}}
</div>
<div id="listing-directions">Directions: {{d.acf.directions}}</div>
<div id="scd-link">View on The Shooting Club Directory</div>
</div>
</div>
<div id="NorthEast" class="desc">
<div ng-controller="regionsLinks1">
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<div id="listing-address-1">
{{d.acf.address_1}},
{{d.acf.address_2}}
{{d.acf.address_3}}
{{d.acf.town}}
{{d.acf.county}}
{{d.acf.postcode}}
</div>
</div>
</div>
</div>
</div>
You can have two Angular applications in page, but only one of them can be auto-bootstrapped with ng-app.
You can instantiate your apps (yes, give them different, meaningful names) by bootstrapping them manually.
In your case, I think it makes more sense to have just one application with two controllers, one for NorthWest and one for NorthEast.
For this case, you can simply have one controller, because both div blocks needs same data to bind. Try it
<script>
var app = angular.module('myApp', []);
app.controller('regionsLinks', function($scope, $http) {
var url = 'http://scd.blaze.wpengine.com/wp-json/posts?type=listings&filter[listing_area]=northwest';
$http.get(url).then(function(data) {
$scope.data = data.data;
});
});
</script>
<div ng-app="myApp" ng-controller="regionsLinks">
<div id="NorthWest" class="desc">
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<img src="{{d.acf.logo}}">
<div id="listing-contact">Contact: {{d.acf.contact}}, {{d.acf.position}}</div>
<div id="listing-address-1">
{{d.acf.address_1}}, {{d.acf.address_2}} {{d.acf.address_3}} {{d.acf.town}} {{d.acf.county}} {{d.acf.postcode}}
</div>
<div id="listing-phone">Telephone: {{d.acf.telephone}}</div>
<div id="listing-mobile">Mobile: {{d.acf.mobile}}</div>
<div id="listing-email">Email: {{d.acf.email}}</div>
<div id="listing-website">Website: {{d.acf.website}}</div>
<div id="listing-established">Established: {{d.acf.established}}</div>
<div id="listing-about">About: {{d.acf.about}}</div>
<div id="listing-mailingaddress">Mailing Address: {{d.acf.mailing_address_}}, {{d.acf.mailing_address_2}}, {{d.acf.mailing_address_3}}, {{d.acf.mailing_town}}, {{d.acf.mailing_county}}, {{d.acf.mailing_postcode}}</div>
<div id="listing-directions">Directions: {{d.acf.directions}}</div>
<div id="scd-link">View on The Shooting Club Directory</div>
</div>
</div>
<div id="NorthEast" class="desc">
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<div id="listing-address-1">
{{d.acf.address_1}}, {{d.acf.address_2}} {{d.acf.address_3}} {{d.acf.town}} {{d.acf.county}} {{d.acf.postcode}}
</div>
</div>
</div>
</div>
Angular.js is pretty new to me. I have learned before the $scope method for the controller and now trying the "this" method. For some reason I can not get my ng-repeat to work. here's my code:
HTML:
<ul class="nav nav-pills">
<li><a ng-click="myCtrl.tab=1" href>one</a></li>
<li><a ng-click="myCtrl.tab=2" href>two</a></li>
<li><a ng-click="myCtrl.tab=3" href>three</a></li>
</ul>
<div ng-controller="imageContr as imageCtrl">
<div ng-show="myCtrl.tab === 1" class="tab">
<h3>ONE title</h3>
<p>hello</p>
<li ng-repeat="item in gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
</div>
<div ng-show="myCtrl.tab === 2" class="tab">
<h3>TWO title</h3>
<p>how are</p>
</div>
<div ng-show="myCtrl.tab === 3" class="tab">
<h3>THREE title</h3>
<p>you?</p>
</div>
</div>
</section>
</body>
</html>
APP.JS:
(function() {
var app = angular.module('myApp', []);
app.controller('myController', function() {
this.tab = 1;
});
app.controller('imageContr', function() {
this.gallery = images;
var images = {
photo: 'image1.jpg'
};
});
})();
Declare images before you assign it, and make it an array
var images = [{ photo: 'image1.jpg' }];
this.gallery = images;
Then in your view:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You are storing the gallery on this of the controller (which is basically the $scope), hence you need to access it in the template via imageContr as well:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You could also consider making gallery an array, so can easily iterate over it. Or you need to use the "iterate over object properties"-syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>
I know this might have been already answered, but I have been unsuccessful in applying any solutions I found to my example. I am trying to enabled pagination on my products list page using UI Bootstrap and allow the user to filter said results with a search.
I have an object that is defined as such:
$scope.products = [{"_id": ObjectID("0000000"), "name":"Product", "description": "Product Description"}];
So far I have been able to pull my products from a restangular service, but I am getting the following console error: Error: [filter:notarray] Expected array but received {} when I added the pagination/search functionality. I know I need to convert my object to an array, but I have not been able to successfully convert it. The two examples I tried are posted below. Any help will be greatly appreciated.
My Products list view
<div ng-controller="paginationCtrl" class="row">
<div class="col-lg-12">
<div class="pull-left">
<form>
<div class="input-group product-searchs" ng-controller="SearchCtrl">
<label class="sr-only" for="searchProducts">Search</label>
<span class="input-group-addon search-icon"><i class="fa fa-search" aria-hidden="true"></i></span>
<input type="text" class="form-control" id="searchProducts" ng-model="search.name" placeholder="Search for products">
<span class="input-group-addon clear-icon">
<button type="button" ng-click="clearSearch()">
<i class="glyphicon glyphicon-remove" aria-hidden="true"></i>
</button>
</span>
</div>
</form>
</div>
</div>
<div class="col-lg-12">
<div class="list-group">
<a ui-sref="productDetails({id:product._id})" class="list-group-item clearfix" ng-repeat="product in filteredProducts = (products | filter: search | startFrom: (currentPage - 1) * itemsPerPage | limitTo: itemsPerPage | orderBy:orderProp)">
<div class="page-header clearfix">
<h2 class="pull-left"><i class="fa fa-diamond"></i> {{product.name}}</h2>
<span class="pull-right product-price {{product.price | currency}}</span>
</div>
{{product.description}}
</a>
</div>
</div>
<div class="col-lg-12">
<pagination class="pull-right" page="currentPage" total-items="totalItems" ng-model="currentPage" max-size="maxSize" ng-change="pageChanged() items-per-page="itemsPerPage" num-pages="numPages"></pagination>
</div>
</div>
I know I might have some extra dependencies injections, which I will remove once I get it working correctly.
My controller
angular.module('gemStoreApp')
.controller('paginationCtrl', ['$scope', '$log', 'filterFilter', 'productsService', 'Restangular', '$filter', function ($scope, $log, filterFilter', productsService, Restangular, $filter) {
$scope.search = {}
$scope.filteredProducts = [];
//Option 1
angular.forEach($scope.products, function(product) {
$scope.filteredProducts.push(product);
});
//Option 2
//for (var key in $scope.products) {
//var tempProducts = {};
//tempProducts[key] = $scope.products[key];
//$scope.filteredProducts.push(tempProducts);
//});
$scope.currentPage = 1;
$scope.maxSize = 100;
$scope.itemsPerPage = 10;
$scope.$watch('search', function(newVal, oldVal) {
$scope.filteredProducts = filterFilter($scope.products, newVal);
$scope.totalItems = $scope.filteredProducts.length;
}, true);
//I also tried this
//$scope.$watch('search, function(newSearch) {
//$scope.filteredProducts = $filter('filter')($scope.products, $scope.search);
// $scope.totalItems = $scope.filteredProducts.length;
//});
}])
My service
angular.module('gemStoreApp.productService',['ngResource'])
.factory('productsService', function(Restangular) {
return Restangular.service('products');
});
My Products Controller
angular.module('gemStoreApp')
.controller('ProductsCtrl', ['$scope', 'productsService', function ($scope, productsService) {
$scope.products = {};
productsService.getList().then(function(products){
$scope.products = products;
});
}]);
Added the Restangular setRestangularFields and setRequestInterceptor methods to my app.js file, which gets the search/filtering function working, but I am still getting an Expected array but received {} error
RestangularProvider.setRestangularFields({
id: '_id.$oid'
});
RestangularProvider.setRequestInterceptor(function(elem, operation) {
if (operation === 'put') {
elem._id = undefined;
return elem;
}
return elem;
});
I have created a Plunker version that appears to be working correctly..
Plunker example.
Created an updated Plunker with the issue I am seeing my local. The issue is that the Pagination is not working correctly. It is displaying only 10 items as I want it to, but clicking on the two does not switch to page 2. Plunker example
I saw several things wrong in your example. I believe you don't need the ng-controller="SearchCtrl" in your html.
Also, the main point of having the filter in your ng repeat is to not use the watch event of the search text input. So you should use the products array and apply the filter against it. If you want to use filteredProducts, I left a function in my example below. I initialized the variables since I don't have access to your restless apis.
var app = angular.module('myApp', []);
app.filter('startFrom', function() {
return function(input, start) {
if(input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.controller('paginationCtrl', ['$scope', '$log', '$filter', function ($scope, $log, $filter) {
$scope.search = {name: "Product"}
$scope.products = [{"_id": "0000000", "name":"Product", "description": "Product Description"},
{"_id": "0000000", "name":"Product 2", "description": "Product Description 2"}];
$scope.filteredProducts = [];
$scope.currentPage = 2;
$scope.maxSize = 100;
$scope.itemsPerPage = 10;
$scope.startFrom = ($scope.currentPage - 1) * $scope.itemsPerPage;
var filterProducts = function(newVal){
$scope.filteredProducts.splice(0, $scope.filteredProducts.length);
angular.forEach($scope.products, function(product) {
if(product.name == newVal){
$scope.filteredProducts.push(product);
}
});
}
$scope.$watch('search.name', function(newVal, oldVal) {
filterProducts(newVal);
$scope.totalItems = $scope.filteredProducts.length;
}, true);
$scope.$watch('currentPage', function(newVal, oldVal) {
$scope.startFrom = ($scope.currentPage - 1) * $scope.itemsPerPage;
}, true);
$scope.$watch('itemsPerPage', function(newVal, oldVal) {
$scope.startFrom = ($scope.currentPage - 1) * $scope.itemsPerPage;
}, true);
}])
<!DOCTYPE html>
<html>
<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="paginationCtrl as ctrl" class="row">
<div class="col-lg-12">
<div class="pull-left">
<div class="input-group product-searchs" >
<label class="sr-only" for="searchProducts">Search</label>
<span class="input-group-addon search-icon"><i class="fa fa-search" aria-hidden="true"></i></span>
<input type="text" class="form-control" ng-model="search.name" placeholder="Search for products" />
<span class="input-group-addon clear-icon">
<button type="button" ng-click="clearSearch()">
<i class="glyphicon glyphicon-remove" aria-hidden="true">test</i>
</button>
</span>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="list-group">
<a ui-sref="productDetails({id:product._id})" class="list-group-item clearfix" ng-repeat="product in products | filter: search.name | limitTo: itemsPerPage | startFrom: 0 ">
{{product.name}}
{{product.description}}
<br/>
</a>
</div>
</div>
<div class="col-lg-12">
<pagination class="pull-right" page="currentPage" total-items="totalItems" ng-model="currentPage" max-size="maxSize" ng-change="pageChanged()" items-per-page="itemsPerPage" num-pages="numPages"></pagination>
</div>
</div>
</div>
</body>
</html>
Edit
After watching your plunker, you do not need to add the filteredProducts to your controller since you are doing the filtering in your view. By adding the filteredProducts to your view, it will also be accessible in your controller with $scope.filteredProducts.
So replace the bottom of your html with the code below and also delete all that code that handles the filteredProducts from your controller:
<div class="col-lg-12">
<div class="list-group">
<a ui-sref="productDetails({id:product._id})" class="list-group-item clearfix" ng-repeat="product in filteredProducts = (products | filter: search.name | limitTo: itemsPerPage | startFrom: 0) ">
{{product.name}}<br/>
{{product.description}}
</a>
</div>
</div>
<div class="col-lg-12">
<pagination class="pull-right" page="currentPage" total-items="filteredProducts.length" ng-model="currentPage" max-size="maxSize" ng-change="pageChanged()" items-per-page="itemsPerPage" num-pages="numPages"></pagination>
</div>
If you want to do everything manually (which I do not recommend), you have to change your html to be product in filteredProducts, when it starts add all your products to the filteredProducts list and keep your code in the controller. Also you will have to fill the filteredProducts list again when the search is empty.
I newly start to use angular.but I have some problem to loading my directive.
I want to load my directive as soon as page loaded.
where I load data-show directive
<div class="row">
<div class="col-md-12">
<article class="row" ng-controller="DataCtrl">
<input type="button" ng-click="getDataList()" >
<h1>Some Content Here</h1>
<ul id="home" bread-crumbs></ul>
<ul class="thumbnails">
<li ng-repeat="data in list" class="col-md-5">
<show-data data="data"/>
</li>
</ul>
</article>
</div>
</div>
showData directive:
app.directive('showData', function () {
return{
restrict: 'E',
replace:true,
templateUrl: 'views/directives/datas.directive.html',
scope: {
data: "="
},
controller:'DataCtrl'
}
})
and template I used in:
<div class="well hoverwell">
<div class="row">
<h2 class="col-md-4">{{data.name}}</h2>
</div>
<div class="row">
<span class="col-md-1">Code:</span>
<span class="col-md-1">{{data.id}}</span>
</div>
<div class="row">
<span class="col-md-1">accountability:</span>
<span class="col-md-1">{{data.parent}}</span>
</div>
<div class="row">
<span class="col-md-1"> :</span>
<span class="col-md-1">{{data.definition}}</span>
</div>
</div>
and my controller
'use strict';
angular.module('app')
.controller('DataCtrl', function ($scope, DataService, $log) {
$scope.getDataList = function () {
var list = DataService.getDataList(1);
list.then(
function (result) {
$log.info(result);
$scope.dataList = result;
}, function (status) {
$log.error(status)
$scope.msg = "error " + status + " has been occur,please report to admin ";
});
};
});
and when I run my app it does not work .
when I watch it in chorome development tools my directive is comment
what is my problem.How can I call this directive as soon as page load.
thx
As you already noticed, you see empty list because your dataList in ng-repeat is not filled yet.
But you have some errors in your code:
First of all - you should never use one controller twice. So you need to create separate controller for your directive.
replace directive parameter is deprecated, better not to use it.
In your DataCtrl you set the dataList variable: $scope.dataList = result;, but in HTML you refer to list variable: <li ng-repeat="data in list" class="col-md-5">.
Maybe that example will help you to figure out with your code.