Limit number of selected items in ng-grid - angularjs

Is there a way to limit the number of selected items in ng-grid?
I did not find a setting to do that, so I am trying to prevent it using a watchCollection in gridOptions.selectedItems.
When the length of selectItems is greater than 5, I try to deselect the last selection but is not working as expected because the item row index seems to be different as rendered:
This is the watcher code:
$scope.$watchCollection('gridOptions.selectedItems', function (newVal, oldVal) {
if ($scope.gridOptions.selectedItems.length > 5) {
for (var i = 0; i < $scope.importableFilesData.length; i++) {
if ($scope.importableFilesData[i] === newVal[0]) {
$scope.gridOptions.selectRow(i, false);
}
}
}

Check your condition in this way. So, you don't have to search last selected row and you can deselect it directly. i've tested it and is working in this way.
$scope.yourGridApi.selection.on.rowSelectionChanged($scope,function(row){
if($scope.yourGrid.gridOptions.selectedItems.length>=5){
row.isSelected = false;
}
});

I have found a solution using beforeSelectionChange property. This property let you set callback that is triggered every time a row is selected. If your return false, the selection will be canceled.
$scope.gridOptions = {
// your grid options ...
beforeSelectionChange: function (row) {
if ($scope.gridOptions.selectedItems.length > 5) {
return false;
}
return true;
}
}

Related

ExtJS - Grid filter with multiple columns and multiple values

I create a grid and a toolbar with Two Menu of menuCheckItem. When i check the menuCheckItem the grid filters even with multiple values and multiple columns.
This working fine, as I have created grid 1st and then the toolbar
this.up('') // Used Instead of Ext.getCmp()
Working FIDDLE - https://fiddle.sencha.com/#view/editor&fiddle/2lop
Now I am trying to create same toolbar along with Menu separately on top 1st and then create grid at below. But while doing this, nly Multiple values is working.
I am trying to filter grid with multiple values as well as multiple columns.
Few things i tried -
// Only Filters One Value at a time with each Columns
store.queryBy(function(record,id){
return (record.get('name') == someValue && record.get('phone') == otherValue);
});
and
// Filters Many Columns with Single Value
filter.add(
property : name, phone
value : "somevalue"
operator : "OR"
);
Is there any way to implement Toolbar 1st and then grid ? And Filter grid with many values and columns simultaneously ?
In this FIDDLE i remade a function(checkchange), which is universal , can be put separately and you'll be able to attach it to every menucheckitem you create. The only thing is that if you add new menucheckitem filter you should name the menucheckitem id with the name of the columnDataIndex-Menu and add this columnDataIndex in menuFilters and thats all.
checkchange: function (checkbox, checked, eOpts) {
var menuFilters = ['name', 'phone'];
var getChecked = function (m) {
var checkedItems = [];
m.items.items.forEach(function (c) {
if (c.checked) {
checkedItems.push(c.text);
}
});
return checkedItems;
};
//
var menus = new Map();
menuFilters.forEach(function (e) {
menus.set(e, Ext.getCmp(e + '-Menu'));
});
//
var fieldValues = [];
menuFilters.forEach(function (e) {
fieldValues.push([e, getChecked(menus.get(e))]);
});
//
var store = checkbox.up('grid').store;
store.clearFilter();
//
if (fieldValues.length > 0) {
store.filterBy(function (record) {
var fV = this.fieldValues;
for (var i = 0; i < fV.length; i++) {
if (fV[i][1].length > 0) {
if (fV[i][1].indexOf(record.get(fV[i][0])) === -1) {
return false;
}
}
}
return true;
}, {
fieldValues: fieldValues
});
}
}

AngularJS smart-table / Select rows - single

i need to make selectable table rows in smart-table
st-select-row="row" st-select-mode="single"
But how can I modify that so one time selectable row stays selected until the next row will be clicked ? I have some links (target will be open in new window) and when they are clicked I get row selected and next time unselected...
Any hints ?
I found solution for my problem. I've modified "select" function from smart-table by adding additional condition (marked bellow as "new condition").
Maybe it will be useful for someone :)
if (mode === 'single') {
if (lastSelected !== row) { // new condition
row.isSelected = row.isSelected !== true;
if (lastSelected) {
lastSelected.isSelected = false;
}
lastSelected = row.isSelected === true ? row : undefined;
}
} else {
rows[index].isSelected = !rows[index].isSelected;
}

Angular ng-repeat filtering

I have a deeply nested object. I have some records which contain 2 fields that show keys of object properties. I also have select needed to search records by property of object and input to search by key of object. So if I choose option1 and type in input some text, it will be shown the matches in the first field (not second!). And it's similar for second field.
How I try to realize:
I wrote a filter http://plnkr.co/edit/z9DEmfYz2grW9UonLcFK?p=preview
.filter('appFilter', function() {
return function(value, select, input) {
var result = [];
input = input.toLowerCase();
var reg = new RegExp(input,'g');
if (angular.isArray(value)) {
if (input === '' || $scope.isFiltering) {
return value;
} else if (select.value === 'Sequence') {
for (let i = 0; i < value.length; i++) {
if (value[i].Sequence.toLowerCase().match(reg)) {
result.push(value[i]);
}
}
return result;
} else if (select.value === 'ID') {
for (let i = 0; i < value.length; i++) {
if (angular.isArray(value[i].Document)) {
for (let j = 0; j < value[i].Document.length; j++) {
if (value[i].Document[j].ID.toLowerCase().match(reg)) {
result.push(value[i]);
}
}
}
}
return result;
} else {
console.log('error');
}
}
}
})
In controller I set to select's ng-model first option: $scope.selectParameter = $scope.parameter[0];
In debug I set to input parameter some value (123 for example).
So I searching record by first field that contains 123 value. And result finds and pushes the object. But in browser shows anything.
What's the problem? And I can't avoid the empty option with '?' value in my select :(
UPDATED
Nearly solve my problem: http://plnkr.co/edit/z9DEmfYz2grW9UonLcFK?p=preview
It filters by appropriate field and input value. But I faced with another troubles.
When input is empty it doesn't show any record. And second is when I choose second option (ID) filter duplicates some records.
Also I try to switch off filter without clearing the input text by clicking on checkbox.
It's what I want to do but it doesn't work:
else if (input === '' || $scope.isFiltering) {
return value;
}
$scope.isFiltering is ng-model for checkbox input
I tried using angulars default filter. I'm not sure if this is exactly what you want, but maybe it helps a little.
.filter('appFilter', function($filter) {
return function(value, select, input) {
if( !angular.isDefined(input) || input.length < 1) {
return value;
}
// Angulars "filter" lets you pass in a object-structure to search for nested fields.
var query =
(select.value === 'Sequence') ?
{Sequence:input} : {Document:{ID:input}};
return $filter('filter')(value, query);
}
})
http://plnkr.co/edit/Egkw9bUvTPgooc0u2w7C?p=preview

angularjs stop incrementing on uncheck of checkbox

I have a checkbox that adds +2 if the user checks it. I need it to only do this one time. Right now the user can constantly add plus 2 which is not what I need. I need it to add it only once. (factors.Delivery is the ng-model)
I also need it to remove the --2 and stop if the checkmark is removed, but right now, it keeps subtracting.
Any help would be appreciated
Even disabling the check after clicking would be good, but it wont disable after clicking only before.
$scope.factors.Delivery = 0;
$scope.increment = function() {
if ($scope.factors.Delivery >= 0) {
$scope.factors.Delivery+=2;
} else {
$scope.factors.Delivery-=2;
}
};
2 is greater than or equal to 0. It sounds like the only acceptable values are 2 and 0 based on your post. I would suggest:
$scope.factors.Delivery = 0;
$scope.increment = function() {
if ($scope.factors.Delivery == 0) {
$scope.factors.Delivery=2;
} else {
$scope.factors.Delivery=0;
}
};`
or using your code, you can disable the checkbox with something like this:
ng-disabled="clickedOnce" on the checkbox and the modifications below.
$scope.factors.Delivery = 0;
$scope.clickedOnce = false;
$scope.increment = function() {
$scope.clickedOnce = true;
if ($scope.factors.Delivery >= 0) {
$scope.factors.Delivery+=2;
} else {
$scope.factors.Delivery-=2;
}
};

UI Grid column filtering works very slow

I have used UI-Grid's built in cell filters but it takes hell lot of time to filter the data even when I have just 20 records.
<div id="grid1" ui-grid="gridCtrl.gridOptions1"
ui-grid-pagination
ui-grid-pinning
ui-grid-resize-columns
ui-grid-move-columns
ui-grid-selection
style="width: 100%; height:680px" class="ui-grid">
and i have just enabled filtering as true.
Please help
actually I found the reason behind this.. I rendered all my rows at once with virtualization Threshold = number of rows, this does not allow the default ui grid rendering algorithm to be used.
Here is a potential workaround...
1. In ui-grid.js, remove the watches set up for each column filter in the header. See if this removes the sluggishness. It will also make the grid not respond to filter changes. Continue to steps 2-4 to make the filters work again.
//$scope.col.filters.forEach(function (filter, i) {
//filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
// if (n !== o) {
// uiGridCtrl.grid.api.core.raise.filterChanged();
// uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
// uiGridCtrl.grid.queueGridRefresh();
// }
//}));
//});
2. In your code, create a function that iterates through the filter terms of each column and creates a string of all filter terms.
function getConcatenatedFilter() {
var concatenatedFilter = "";
var api = this.getGridApi();
if (api) {
for (var i = 0; i < api.grid.columns.length; i++) {
concatenatedFilter += i + ":";
var column = api.grid.columns[i];
var term = column.filters[0].term || "";
if (term) {
concatenatedFilter += term;
}
}
}
return concatenatedFilter;
}
3. Create one watch that monitors the concatenated filter function above. When it fires, create a timeout to that sets another scope variable called filtersCheck. The timeout will wait 200ms before changing filtersCheck.
$scope.$watch(function() {return getConcatenatedFilter();},
function (newVal: string, oldVal: string) {
if (filterTextTimeout) {
$timeout.cancel(filterTextTimeout);
}
var tempFiltersString = newVal;
filterTextTimeout = $timeout(() => {
$scope.filtersCheck = tempFiltersString;
}, 200);
});
4. Finally, set up a final watch for filtersCheck which will refresh the grid when it fires.
$scope.$watch('filtersCheck', (newVal, oldVal) => {
if (newVal && oldVal && newVal !== oldVal) {
gridApi.grid.queueGridRefresh();
}
});

Resources