I'm using this angular filter to filter out objects in an array whose localteam_id properties match a value that is held in $scope.whichMyteam. This works fine.
VIEW
<div ng-repeat="fixture in getFixtures | filter: {localteam_id: whichMyteam} ">
I want to extend the filter however, to include a section criterion: so it will, in effect, be:
<div ng-repeat="fixture in getFixtures | filter: {localteam_id: whichMyteam && visitorteam_id: whichMyteam} ">
...but a) this doesn't work, and b) even if it did, it's getting a little cumbersome and seems that it would justify making a custom filter.
So, I tried to make one. The problem I ran into is I need to reference the $scope.whichMyteam value in the filter, but it seems the filter module can't accept/understand $scope. This is crucial for the filter to work in my instance, so I'm not sure how to resolve this.
My filter so far looks like this:
app.filter('myFixtures', function() {
return function(input) {
angular.forEach(input, function(o) {
output = [];
if (o.localteam_id === $scope.whichMyteam) {
output.push(o);
}
return output;
})
};
});
The above is a simplified version which only attempts to match one property (just did this to test it and reduce the number of moving parts). When I call it in the view though...
<div ng-repeat="fixture in getFixtures | myFixtures">
...it doesn't work. Console logs '$scope is not defined'.
UPDATE: I tried this, still not working!
FILTER
var myFilters = angular.module('myFilters', [])
myFilters.filter('myFixtures', function(whichMyteam) {
return function(input) {
angular.forEach(input, function(o) {
output = [];
if (o.localteam_id === whichMyteam) {
output.push(o);
}
return output;
})
}
});
VIEW
<div ng-repeat="fixture in getFixtures | myFixtures(whichMyteam)">
Console is logging a syntax error (I think...)
angular.js:13236 Error: [$parse:syntax]
How about having your filter function return a function.
app.filter('myFixtures', function() {
return function(input, whichMyteam) {
output = [];
angular.forEach(input, function(o) {
if (o.localteam_id === whichMyteam) {
output.push(o);
}
})
return output;
};
});
Then call the filter function passing in your variable
<div ng-repeat='fixture in getFixtures | myFixtures:whichMyteam'>
--- example
angular
.module('app', [])
.filter('otherFilter', otherFilter)
.controller('controller', controller);
controller.$inject = ['$scope'];
function controller($scope) {
$scope.things = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
$scope.modVal = 2;
console.log('controller');
$scope.myFilter = function(x) {
return function(y) {
return (y % x) === 0;
}
};
}
function otherFilter() {
return function(y, x) {
var out = [];
angular.forEach(y, function(val) {
if ((val % x) === 0) {
out.push(val)
}
});
return out;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='controller'>
<div ng-repeat='thing in things | filter:myFilter(modVal)'>
{{ thing }}
</div>
<br/>
<div ng-repeat='thing in things | otherFilter:modVal'>
{{ thing }}
</div>
</div>
You have 2 problems here:
1. How to pass a param, html:
<div ng-repeat="fixture in getFixtures | myFixtures:whichMyteam">
js:
myFilters.filter('myFixtures', function() {
return function(input, whichMyteam) {
...
Do not place return statement inside forEach -- it does not make what you think;)
So finally your filter is:
myFilters.filter('myFixtures', function() {
return function(input, whichMyteam) {
output = [];
angular.forEach(input, function(o) {
if (o.localteam_id === whichMyteam) {
output.push(o);
}
})
return output;
}
});
http://plnkr.co/edit/0XFfI8hIdCaJ19gJRYr2?p=preview
Related
How could i return couple name:[apple, orange, carrot]
[http://jsfiddle.net/GruffBunny/QHtD8/2/]1
function MyCtrl($scope) {
$scope.products = [
{id:"1",type:"fruit"},
{id:"2",type:"meat"},
{id:"3",type:"drink"},
{id:"4",type:"vegetable"},
{id:"5",type:"dairy"}
];
$scope.fruitOrVeg = function(product){
return product.name == ['1','4','5'];
};
Thank you very much
Change your template, to call function:
<li ng-repeat="item in products | filter:fruitOrVeg()">{{item.name}}</li>
and filter function, return new function
$scope.fruitOrVeg = function() {
return function(item) {
return ['1', '4', '5'].indexOf(item.id) > -1;
}
};
Added JSFiddler
Try using an AngularJS custom filter.
app.filter('filterByFruitOrVeg', function() {
return function(array) {
arr = arr.filter(payment, function(objectInArray) {
return objectInArray.type === 'fruit' || objectInArray.type === 'vegetable';
});
}
});
I have an array in AngularJS controller like this:
$scope.persons = [{name:'Joey', age:'27'},{name:'Lucy', age:'22'}]
I have got a name 'Lucy', how can I get the age of the name in the controller (not in HTML)?
I've created a plunk here that outlines a single result, with just the age, as well as multiple results.
This could also be implemented within a filter, which is documented on the Angular site here: https://docs.angularjs.org/api/ng/filter/filter
https://plnkr.co/edit/OFRMzpQrZfTOnaFyJP7Z?p=info
angular.module('plnk',[]).controller('plnkCtrl', function($scope){
// Note, I added a second Joey here to test the multiple function.
// For output, check the browser console.
$scope.persons = [{name:'Joey', age:'27'},{name:'Joey', age:'28'},{name:'Lucy', age:'22'}]
console.log('Single -> ', getAgeSingle('Lucy'));
console.log('Multiple ->',getAgeMultiple('Joey'));
function getAgeMultiple(personLookup) {
var results = [];
angular.forEach($scope.persons,function(person){
if (person.name === personLookup) {
results.push(person);
// or results.push(person.age) for age only
}
});
return results;
}
function getAgeSingle(personLookup) {
var result = '';
angular.forEach($scope.persons,function(person){
if (person.name === personLookup && !result) {
result = person.age;
}
});
return result;
}
});
Just loop over the array and check, like this:
function getAge(name)
{
for (var i = 0; i < $scope.persons.length; i++)
{
var person = $scope.persons[i];
if (person.name === name)
{
return parseInt(person.age, 10);
}
}
return undefined;
}
This has a couple caveats -- if you have dupes you'll only get the first one and it runs in linear time. If you control the data source it'd be better to use a JS object/hashmap/dictionary/whatever you want to call it.
If you wanted to loop through the scope:
$scope.persons = [{name:'Joey', age:'27'}, {name:'Lucy', age:'22'}]
function getAge(name) {
angular.forEach($scope.persons, function (value, index) {
if (value.name === name) {
return parseInt(value.age, 10);
}
});
return undefined;
}
The HTML way:
<div ng-app="myApp" ng-controller="MainCtrl">
<table>
<tr ng-repeat="person in persons">
<td>Name: {{person.name}} Age: {{person.age}}</td>
</tr>
</table>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.persons = [{name:'Joey', age:'27'}, {name:'Lucy', age:'22'}];
});
I want to change the color of the word in the sentence How can i do that?
Controller code:
app.controller("myController",function($scope){
$scope.phrase="This is a bad phrase";
});
app.filter('censor', function(){
return function(input){
var cWords = ['bad', 'evil', 'dark'];
var out = input;
for(var i=0; i<cWords.length;i++){
out = out.replace(cWords[i], <span class="blue"></span>);
}
return out;
};
})
My view:
{{phrase | censor}}
First of all, if you want to bind html in your filter, you need to use ngSanitize and binding with the directive: ng-bind-html instead of {{ }}, like this:
<p ng-bind-html="ctrl.phrase | censor"></p>
In your js file you need to check if the phrase contain any of the words you want to filter out, then update the phrase.
angular
.module('app', ['ngSanitize'])
.controller('MainCtrl', function() {
var ctrl = this;
ctrl.phrase = 'This is a bad phrase';
})
.filter('censor', function() {
return function(input) {
var cWords = ['bad', 'evil', 'dark'];
var splitPhrase = input.split(' ');
var out = splitPhrase.reduce(function(acc, curr) {
if (cWords.indexOf(curr) > -1) {
acc.push('<span class="blue">' + curr + '</span>');
} else {
acc.push(curr);
}
return acc;
}, []);
return out.join(' ');
}
});
You can find an example here: http://jsbin.com/koxekoq/edit?html,js,output
Say I create an Angular app and write some new filters: Show only odds, and show only lucky numbers.
There's an oddList filter and a luckyList filter:
var app = angular.module('app', []);
app.filter('oddList', function() {
return function(items) {
var filtered = [];
angular.forEach(items, function(item) {
if (item % 2 !== 0)
filtered.push(item);
});
return filtered;
};
});
app.filter('luckyList', function() {
return function(items) {
var filtered = [];
angular.forEach(items, function(item) {
if (item === 2 || item === 7 || item === 11)
filtered.push(item);
});
return filtered;
};
});
In the view portion, I can chain these filters:
<ul><li ng-repeat="number in numbers | oddList | luckyList">{$number}</li></ul>
When this works, I should see 7 and 11 remaining.
I want to make my filters variable for this ng-repeat. Is there something I can do that's similar to this process?
Say I name the variable filter filter:listFilter so that in our controller, we can dynamically update $scope.listFilter.
<ul><li ng-repeat="number in numbers | filter:listFilter">{$number}</li></ul>
And the controller with pseudo code:
app.controller('main', function($scope, $filter) {
$scope.numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
$scope.listFilter = $filter('oddList | luckyList');
});
Any idea how I could chain (variable) filters in the controller? Would like to be able to toggle between just odd, just lucky and/or both.
An approach is to use a function to return the filtered data:
function MainCtrl($scope, $filter) {
$scope.numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
$scope.filteredNumbers = function() {
var result = $scope.numbers;
if ($scope.oddListEnabled) {
result = $filter('oddList')(result);
}
if ($scope.luckyListEnabled) {
result = $filter('luckyList')(result);
}
return result;
};
}
And the template:
<ul>
<li ng-repeat="number in filteredNumbers()">
{{number}}
</li>
</ul>
Here is a plunkr: http://plnkr.co/edit/4ectDA?p=preview
If I have the following simple controller & service.
<div ng-controller="MessagesCtrl">
<ul>
<li ng-repeat="message in data.messages">
{{ message }}
</li>
</ul>
</div>
myApp.factory('Data', function () {
var _messages = [];
return {
messages: _messages,
getMessages: function() {
$http.get('/messages').then(function(response) {
_messages = response.data;
});
}
};
});
function MessagesCtrl($scope, Data) {
$scope.data = Data;
$scope.data.getMessages();
}
I would expect the messages model to auto-update when the AJAX request completes and fills the object, however it does not. How is this supposed to work? (I'm sort of asking what the best practice is for this structure).
Edit - working solution:
<div ng-controller="MessagesCtrl">
<ul>
<li ng-repeat="message in data.messages">
{{ message }}
</li>
</ul>
</div>
myApp.factory('Data', function () {
return {
getMessages: function() {
var _this = this;
$http.get('/messages').then(function(response) {
_this.messages = response.data;
});
}
};
});
function MessagesCtrl($scope, Data) {
$scope.data = Data;
$scope.data.getMessages();
}
I'm fairly certain you have a JavaScript issue here and not an AngularJS related issue. Let's remove the AngularJS related code and leave just the JavaScript piece:
function factory() {
var _messages = [];
return {
messages: _messages,
getMessages: function() {
_messages = [1, 2, 3, 4];
}
}
}
> var test = factory();
undefined
> test.messages
[]
> test.getMessages()
undefined
> test.messages
[]
test.messages points to the origin _messages array whereas later on _messages is getting changed but test.messages is not.