I created an array that has the following format...
$scope.myArr = [arg1, arg2];
Now I want to create a custom filter that will take the array as a parameter and compare to another array, for example I want to use it as so...
<div class="form-container" ng-repeat="formblock in forms | filter:dateFilter(myArr)">
This way every formblock will be compared to the array, so if formblock.date has either arg1 or arg2 then these will show, otherwise hide everything else.
Is this possible?
Your html with custom Angular#Filter should be
<div class="form-container" ng-repeat="formblock in forms | dateFilter:myArr">
Your forms is passed as firsr parameter implicitely and passed the additional parameter with : after filter name.
JS :
Filter :
app.filter('dateFilter', function() {
var boolFound = false;
return function(arrForm, arrArg) {
arrForm.forEach(function(val, key) {
var boolFound = false;
arrArg.forEach(function(val1, key1) {
if (val.date === val1) {
boolFound = true;
}
});
if (boolFound === false) {
arrForm.splice(key, 1);
}
});
return arrForm;
}
})
Here is the updated Fiddle
Related
I normally filter an array using input tag like this :
$scope.filtername = function (vname) {
//repopulate the array from a copy every time input changes
$scope.items = $scope.items_filter;
//filter array if vname is a substring from item.name
if (vname && vname.trim() != '') {
$scope.items = $scope.items.filter((item) => {
return (item.name.toLowerCase().indexOf(vname.toLowerCase()) > -1);
})
}
};
<input type="search" ng-model="namev" ng-change="filtername(namev)">
But since the user needs to filter the array while editing hundreds of items with unsaved changes, I'm not sure how to proceed. Should I use ng-show instead ? or is there a better vanilla javascript way?
do you have a better way to filter array using a search input?
One approach is to create a custom filter:
app.filter("myFilter", function() {
return function(inputArr,vname) {
//repopulate the array from a copy every time input changes
var result = inputArr.concat();
//filter array if vname is a substring from item.name
if (vname && vname.trim() != '') {
result = result.filter((item) => {
return (item.name.toLowerCase().indexOf(vname.toLowerCase()) > -1);
});
};
return result;
};
})
Usage:
<input type="text" ng-model="namev" />
<div ng-repeat="item in items | myFilter : namev">
{{item.name}} {{item.contents}}
</div>
For more information, see AngularJS Developer Guide - Creating Custom Filters
can you explain the purpose of inputArr ?
The first argument to the filter function is the array to be filtered. This way it can be used with other scope variables:
<div ng-repeat="item in items | myFilter : namev">
{{item.name}} {{item.contents}}
</div>
<div ng-repeat="o in otherItems | myFilter : namev">
{{o.name}} {{o.contents}}
</div>
When AngularJS pipes data to a filter, it invokes the filter function with the data as the first argument. Subsequent arguments come from expressions separated by colons (:).
For more information, see AngularJS Developer Guide - Using filters in view templates
I am trying to look for texbox values matching an array I have provided a code snippet below:
$('#message').on('keyup', function () {
suggest_array_sample = [
{ array_val: "#{person1}" },
{ array_val: "#{person2}" },
{ array_val: "#{person3}" }
];
found_variable_array = [];
$.each(suggest_array_sample, function (key, value) {
console.log(value);
if ($.inArray(value, textbox_value)) {
console.log('found');
found_variable_array.push(value);
} else {
console.log('not found');
}
})
console.log(found_variable_array);
});
<textarea id="message"></textarea>
The problem is it always return the whole array instead of just the matches the ouput should be when I type #{person1} on the textbox the output should be
[{array_val:"#{person1}"}] //expected output
[{array_val:"#{person1}"},{array_val:"#person2"}]// expected output when two or more matches are found on the textbox
instead of
[{array_val:"#{person1}"},]{array_val:"#{person2}",{array_val:"#{person3}"}] //current output
is this possible using the inArray() or do I need to change the code.
use filter method of Array.
yourArray.filter ( yourArrayModel => yourArrayModel.fieldValue === yourSearchValue )
In your case yourSearchValue can be “{#person1}”
For more information, look for filter method documentation, i hope this is what you want.
$.inArray return a position, if not found return -1 else return >= 0
The $.inArray() method is similar to JavaScript's native .indexOf()
method in that it returns -1 when it doesn't find a match. If the
first element within the array matches value, $.inArray() returns 0
Try this code
$('#message').on('keyup', function () {
textbox_value = $(this).val();
suggest_array_sample = ["#{person1}", "#{person2}", "#{person3}"];
console.log($.inArray(textbox_value, suggest_array_sample));
});
It's not entirely clear what you're trying to achieve. I've written something using $.inArray that tells you the array index of the found value. You need to use .map() on the array to extract the val you want.
EDIT:
From what I understood of your comment, I've now had the value be added to found_value_array each time the value is found.
Or is it that you want an array to be returned because the same value might appear multiple times?
let found_variable_array = [];
$('#message').on('keyup',function(){
suggest_array_sample = [
{array_val:"#{person1}"},
{array_val:"#{person2}"},
{array_val:"#{person3}"}
]
let index = $.inArray($(this).val(), suggest_array_sample.map(o => o.array_val));
if (index >= 0) found_variable_array.push(suggest_array_sample[index]);
console.log(found_variable_array);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="message"></textarea>
After combining ideas presented here this method work for me
match_value = suggest_array.filter(function(result){
if(textbox_value){
return textbox_value.search(result)>-1
}
else{
return false
}
})
console.log(match_value);
I'm trying to filter a list of people by the starting letter of their first name in an AngularJS repeater.
The repeater is as follows:
<li ng-repeat="person in people | orderBy: 'firstname' | firstLetter:'firstname':'A'">
<a ui-sref="people.details({ personId: {{person.id}} })">
<span class="list__icon"><img src="img/avatar.png"></span>
<span class="list__text">
<span class="list__text__name">{{person.firstname}} <b>{{person.lastname}}</b></span>
</span>
</a>
</li>
So I order it by first name and then use a custom filter called firstLetter:
.filter('firstLetter', function () {
return function (input, letter) {
input = input || [];
var out = [];
input.forEach(function (item) {
if (item.charAt(0).toLowerCase() == letter) {
out.push(item);
}
});
return out;
}
});
However I get an error that charAt isn't a function... Am I passing the parameters to the filter incorrectly?
Your firstLetter filter is missing an additional param. The first param input refers to the array which is being repeated through (in this case, people). The second param, letter should actually be the third param of your filter declaration.
.filter('firstLetter', function () {
return function (input, key, letter) {
input = input || [];
var out = [];
input.forEach(function (item) {
console.log('item: ', item[key][0].toLowerCase());
console.log('letter: ', letter);
if (item[key][0].toLowerCase() == letter.toLowerCase()) {
out.push(item);
}
});
return out;
}
});;
Yes you are passing parameters to filter incorrectly. By default filter input i.e your array will get passed as a first parameter.
.filter('firstLetter', function () {
return function (objects, input, letter) {
var out = [];
angular.forEach(objects,object){
var item = object[input];
if (item.charAt(0).toLowerCase() == letter.toLowerCase()) {
out.push(object);
}
});
return out;
}
});
I would like to know what is the most elegant and simple way to implement this.
I need to add a filter expression for a ng-repeat that would filter 2 conditions from one property.
In this example http://plnkr.co/edit/OMQxXvSjtuudMRGE4eZ8?p=preview
If you enter A, it would display checkbox for A,
enter B - display checkbox for B.
But I want to display the specified checkboxes plus anything with empty condition.
There is no condition for C, so:
if you enter A, I want to display both A and C checkboxes,
enter B, I want to display both B and C checkboxes.
I would create custom filter like:
app.filter('myfilter', function() {
return function( items, condition) {
var filtered = [];
if(condition === undefined || condition === ''){
return items;
}
angular.forEach(items, function(item) {
if(condition === item.condition || item.condition === ''){
filtered.push(item);
}
});
return filtered;
};
});
and usage:
<span ng-repeat="charge in charges | myfilter:level.condition">
See Demo in Plunker
It looks pretty elegant and clear.
Hope it will help
I think you can do this pretty easily with just a filter expression function on your scope like this;
$scope.filterExpression = function(charge) {
return (!$scope.level || !charge.condition ||
($scope.level.condition.toUpperCase() === charge.condition.toUpperCase()));
}
and call it like this;
<span ng-repeat="charge in charges | filter:filterExpression">
plunkr (corrected)
you can use :
data-ng-repeat="charge in charges | filter:searchText" data-ng-if="filter = searchText.Name"
Use two ng-repeats, one after another:
1st : Filter on anything that has checkbox checked AND has a condition
2nd : Filter on things that don't have conditions
Actually the question is related to typeahead bootstrap
because I need to define an array of values to show in input text by using autocomplete.
Anyway, the goal is just to define a function which read an array of objects and return an array of string.
Here is my code(1).
The goal of (1) is:
1) get an array of strings from an array of objects.
2) filter this array rejecting some elements.
It does not work because the element I want to reject persists in the array.
In fact in the autocomplete I get false value, actually it brokes the code because false is not expected by typeahead.
How should fix the code and maybe improve it?
(1)
element.typeahead({
source: function ( {
var users = _.map(app.userCollection.models, function (model) {
if (model.get('id') === app.currentUser.id) {
return false;
}
return model.get('first_name') + ' ' + model.get('last_name');
});
console.log(users); // [false, 'some name'];
_.reject(users, function(name) {
return name === false;
});
console.log(users); // [false, 'some name'];
// why does the false value persist?
return users;
}
});
Underscore methods don't usually operate on the array itself, but they return a new array, but I suggest checking the underscore docs on each function individually for confirmation. In this case we can safely assume that reject returns some new array, according to this sentence in the underscore docs:
Returns the values in list without the elements that the truth test (iterator) passes.
What you are currently doing is:
_.reject(users, function(name) {
return name === false;
});
So, you don't actually save your results anywhere. To preserve a reference to the array without the unwanted elements do this:
users = _.reject(users, function(name) {
return name === false;
});
That would yield the result you want, but let me give you a refactoring hint:
Use backbone's own methods as far as you can, it'll make for more readable code
source: function() {
// filter the collection down to the users you want
var users = app.userCollection.filter(function(model) {
return model.id === app.currentUser.id;
});
// -> users is now an array of models
// use map to transform each wanted user to a string giving its full name
users = _.map(users, function(user) {
return user.get('first_name')+' '+user.get('last_name');
});
// -> users is now an array of strings
return users;
}
Hope this helps!