I am using AG grid.
TextFilter is working fine. but i want my ag grid to show rows when i search with string seperated with commas(",").
Eg : when i search with "abc,def,xyz", it should give the result that rows contains abc or def or xyz.
Thanks in advance
Look at using the textCustomComparator option, documented here: https://www.ag-grid.com/javascript-grid-filter-text/#text-custom-comparator
Here is an example of how it could be accomplished:
filterParams: {
filterOptions: ["contains"],
textCustomComparator: function(filter, value, filterText) {
// get array of comma separated values
const filterValues = filterText.split(',');
// loop through filterValues and see if the value contains any of them
return filterValues.some((item) => {
return value.indexOf(item) >= 0;
});
}
}
Another option is to use a custom filter, which is documented here: https://www.ag-grid.com/javascript-grid-filter-custom/
Related
I want to check if the first column of each row's text starts with "AA", "BB" or "CC". But I couldn't manage it on div table. I can only select and check the first row (code below). But I also tried with selecting the whole column and tried with using cy.each & cy.wrap and got errors too.
How can I check the first column for each row's text? (Table has 40-45 rows.)
The table looks like this:
Right now I can only check the first row with the code below. How can I check all the rows like this? Is the code below clear to you by the way?
cy.get('div[row-index="0"]')
.eq(1)
.invoke('text')
.then(text => {
const productID = text.trim();
let correctProductIDPrefix = false;
['AA', 'BB', 'CC'].forEach(possibleProductIDPrefix => {
if (!correctProductIDPrefix) {
correctProductIDPrefix = productID.startsWith(possibleProductIDPrefix);
}
});
expect(correctProductIDPrefix).to.be.true;
});
Thanks in advance!
To perform the same test on all rows
select all the rows (change [row-index="0"] to [row-index])
use .each() to run test on all rows
sub-select just the column you want, in case some other column also has the prefix and gives you a false-positive result
use Array.some() method to check at least one prefix matches
const possibleProductPrefixes = ['AA', 'BB', 'CC'] // define once outside test
cy.get('div[row-index]') // selects every row
.each($row => {
const $col = $row.find('[col-id="orderNumber"]') // pick out the column
const productId = $col.text().trim()
const correctProductIDPrefix = possibleProductPrefixes.some(prefix => {
return productId.startsWith(prefix)
})
expect(correctProductIDPrefix).to.be.true;
});
Ref Array.prototype.some()
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
You can do something like this:
let prefix = ['AA', 'BB', 'CC']
cy.get('.ag-cell-value').each(($ele, index) => {
expect($ele.text().trim().startsWith(prefix[index])).to.be.true
})
I built a custom component that filters an array of objects. The filter uses buttons, sets from active to non-active and allows more than one option on/off at the same time.
StackBlitz of my attempt - https://stackblitz.com/edit/timeline-angular-7-ut6fxu
In my demo you will see 3 buttons/options of north, south and east. By clicking on one you make it active and the result should include or exclude a matching "location" either north, south and east.
I have created my methods and structure to do the filtering, I'm struggling with the final piece of logic.
So far I have created a method to create an array of filtered locations depending on what the user clicks from the 3 buttons.
Next this passes to my "filter array" that gets the logic that should compare this filtered array against the original to bring back the array of results that are still remaining.
Its not quite working and not sure why - I originally got this piece of functionality working by using a pipe, but fore reasons do not want to go in that direction.
//the action
toggle(location) {
let indexLocation = this.filteredLocations.indexOf(location);
if (indexLocation >= 0) {
this.filteredLocations = this.filteredLocations.filter(
i => i !== location
);
} else {
this.filteredLocations.push({ location });
}
this.filterTimeLine();
}
// the filter
filterTimeLine() {
this.filteredTimeline = this.timeLine.filter(x =>
this.contactMethodFilter(x)
);
}
//the logic
private contactMethodFilter(entry) {
const myArrayFiltered = this.timeLine.filter(el => {
return this.filteredLocations.some(f => {
return f.location === el.location;
});
});
}
https://stackblitz.com/edit/timeline-angular-7-ut6fxu
Sorry for my expression but u have a disaster in your code. jajaja!. maybe u lost that what u need but the logic in your functions in so wrong. comparing string with objects. filter a array that filter the same array inside... soo u need make a few changes.
One:
this.filteredLocations.push({location});
Your are pushing object. u need push only the string.
this.filteredLocations.push(location);
Two:
filterTimeLine() {
this.filteredTimeline = this.timeLine.filter(x =>
this.contactMethodFilter(x)
);
}
in this function you filter the timeLine array. and inside of contactMethodFilter you call filter method to timeLine again....
See a functional solution:
https://stackblitz.com/edit/timeline-angular-7-rg7k3j
private contactMethodFilter(entry) {
const myArrayFiltered = this.timeLine.filter(el => {
return this.filteredLocations.some(f => {
return f.location === el.location;
});
});
}
This function is not returning any value and is passed to the .filter
Consider returning a boolean based on your logic. Currently the filter gets undefined(falsy) and everything would be filtered out
Beginner in Angular, so it might sound a little silly question, but couldn't find an answer yet.
I have two select boxes -
one which describes a module which I use as ng-model=module ([x,y,z]).
The second one is an array which in each index I have an array with 3 attributes - id, name and module( [1, "first", x])
I am using ng-repeat for my second select box and I want to filter according to the module and the third index.
Basically, it's something like that: "option in options | filter: module === secondbox[2]", but obviously I'm doing something wrong, maybe by syntax.
Please assist me to execute it right. Thanks!
I think it would be best to write a custom filter for this:
.filter('moduleMatch', function() {
return function(items, module, itemIndex, moduleIndex) {
let out = [];
// make sure a filter value was supplied
if (module) {
items.forEach(i => {
if (i[itemIndex] === module[moduleIndex]) {
out.push(i);
}
});
// return the items that matched the filter value
return out;
}
// no filter value was supplied - return the unfiltered collection
return items;
}
})
Then use it in the second select:
"option in options | moduleMatch: module:2:2"
I need to Create a Kendo ui grid. Since this has many filters, I need to have 4 regular filters and rest should be able to add dynamically according to users choice. Can someone provide assistance on this?
In order to filter by text box you can hook up a keyUp event in order to retrieve the value. You can then add this as a filter to the existing filter object.
$('#NameOfInput').keyup(function () {
var val = $('#NameOfInput').val();
var grid = $("#yourGrid").data("kendoGrid");
var filter = grid.dataSource.filter();
filter.filters.push({
field: "NameOfFieldYouWishToFilter",
operator: "eq",
value: val,
FilterName: "UniqueIdentifierForFilter"
});
grid.dataSource.filter(filter);
});
Using a drop down box, you can achieve the desired functionality by using the onChange event, get the value using $('#yourDropDown').val();.
The FilterName is optional incase you require additional logic to add/remove filters. i.e. you can use this to determine whether the filter already exists in the array and if so you can use splice to remove it.
EDIT
Using FilterName you can search to see if a filter already exists and remove it:
var filterIndex = filter.filters.map((e: any) => { return e.FilterName }).indexOf("UniqueIdentifierForFilter");
if (filterIndex > -1)
{
filter.filters.splice(filterIndex, 1);
}
For #lakshan, while this is largely correct, you will get an error if there are no filters at first. I found this answer when I encountered the undefined filter error. My full solution for adding a filter, either to an undefined filter set, or along with an existing one:
var grid = $("#ActivityGrid").data("kendoGrid");
var dataSource = grid.dataSource;
var gridFilter = dataSource.filter();
var upcomingFilter = {
field: "ActivityDate",
operator: "gte",
value: new Date(),
FilterName: "UpcomingOnly"
};
if ($("#UpcomingOnlyCheckbox")[0].checked) {
if (gridFilter == undefined) {
dataSource.filter(upcomingFilter);
}
else {
gridFilter.filters.push(upcomingFilter);
dataSource.filter(gridFilter);
}
}
I have the following code in my controller:
$scope.filteredTransactions = $scope.invoiceTransactionsObject.transactions.concat(); // make a copy of the initial array
if ($scope.searchTerm.message)
{
var search = $scope.searchTerm.message;
$scope.filteredTransactions = $filter('filter')($scope.filteredTransactions, ({ message: search } || { item: search }));
}
I want to be able to filter by typing some value and search either in the message column or item column. According to How to filter multiple values (OR operation) in angularJS it should work, but it doesn't and if I type something that can be found in the message, it works, but when I type something from the item, it returns empty array.
Do you see where is my mistake?
Update Deleted irrelevant/mistaken initial answer
Since you're applying $filter inside a JS script, and it doesn't use any of the advanced features of $filter, I'd switch over to the JS-native method of filtering an array:
$scope.filteredTransactions = $scope.invoiceTransactionsObject.transactions.concat(); // make a copy of the initial array
if ($scope.searchTerm.message)
{
var search = $scope.searchTerm.message;
$scope.filteredTransactions = $scope.filteredTransactions.filter(function (trans) {
return trans.message.toLowerCase().indexOf(search) >= 0 || trans.item.toLowerCase().indexOf(search) >= 0;
});
}
...assuming that $filter is case-insensitive and matches anywhere in the string. If that's not the functionality of $filter and/or not what you want, you'd adjust the code accordingly.