Filtering a single column with OR operator - kendo-ui

Would like to do filtering in kendo grid within the same column for getting a union of values coming from a multiselect field:
$('#btnSearchRoles').click(function (e) {
e.preventDefault();
//process searched roles
var multiselect = $("#RoleSubroleId").data("kendoMultiSelect");
// get data items for the selected options.
var dataItem = multiselect.dataItems();
var filterCode = "[";
for (var i = 0; i < dataItem.length; i++) {
filterCode += "{ field: 'RolesAsString', operator: 'contains', value: '" + dataItem[i].Name + "'},"
}
filterCode += "]";
//start filtering
var dataSource = $("#grid").data('kendoGrid').dataSource;
dataSource.filter({
logic: "or",
filters: filterCode
});
});
Even though filterCode gets correctly populated the filters do not reach the DataSourceRequest request parameter.

I used push method for JS arrays to replace string composition of the filter:
$('#btnSearchRoles').click(function (e) {
e.preventDefault();
//process searched roles
var multiselect = $("#RoleSubroleId").data("kendoMultiSelect");
// get data items for the selected options.
var dataItem = multiselect.dataItems();
var setFilter = { logic: "or", filters: [] };
for (var i = 0; i < dataItem.length; i++) {
setFilter.filters.push({ field: "RolesAsString", operator: "contains", value: dataItem[i].Name });
}
//start filtering
var dataSource = $("#grid").data('kendoGrid').dataSource;
dataSource.filter(setFilter);
});

Related

Add custom command to Kendo UI dynamic datasource / grid

I'm using Kendo UI javascript framework in an ASP.NET MVC application.
I have to load dynamic data, provided by my server, in my Kendo UI Grid, so I don't want to use datasource schema and columns definition, in no case.
An example of my data is : PersonID, Data1, Data2, Date3 ...
To load dynamic data in Kendo UI Grid I use the following code: (JsFidlle Example)
var grid = $("#grid").kendoGrid({
scrollable: false,
sortable: true
}).data("kendoGrid");
var ds = grid.dataSource;
grid.columns = [];
ds.data([{one: 1, two: 1, three: 3, four: 4}]);
Starting from this example, I'm curious to know if, with this management, I can put in each row a command / custom command like "Delete". (Example)
Eventually, how can I handle the command's behavior ? (would be nice to see a confirm window after the click over the command)
Thanks for the attention !
Get your data first, then create an array for the grid columns based on the data and add a column for the buttons.
Create the grid and attach handler to every button.
http://jsfiddle.net/cp67fpw1/2/
Creating the grid:
var columns = [],
data = [{
one: 1,
two: 1,
three: 3,
four: 4,
five: 5
}],
grid;
for (var cx in data[0]) {
if (data[0].hasOwnProperty(cx)) {
columns.push({
field: cx
})
}
}
columns.push({
field: '',
template: '<a class="k-button" command="doit">do it</a><a class="k-button" command="doitagain">do it again</a>'
});
grid = $("#grid").kendoGrid({
columns: columns,
dataSource: new kendo.data.DataSource({
data: data
}),
scrollable: false,
sortable: true
}).data("kendoGrid");
Adding the button handler:
$('#grid').on('click', '[command="doit"]', doit);
function doit(e) {
var dataItem = grid.dataSource.getByUid($(this).closest('tr').data('uid'));
}
I resolved out with this solution : https://jsfiddle.net/Endrik/smLfh67e/1/
It's very similar to Frederic solution but with few changes.
1) I start from a datasource object, cause I will get my data from remote
If you change the type of data loading in the DataSource object, the example should work equally.
var myDataSource = new kendo.data.DataSource({
data: [{
one: "1",
two: "2",
three: "3",
four: "4"
}, {
one: "5",
two: "6",
three: "7",
four: "8"
}]
});
myDataSource.fetch();
2) In order to have dynamic columns, I have to convert the data present in my datasource object into an array of values. (Like Frederic's startup collection of objects)
var myDataSourceRowsNumber = myDataSource.total();
var rows = [];
var columns = null;
var columnsCount = 0;
for (var i = 0; i < myDataSourceRowsNumber; i++) {
var entryArray = [];
var dataItem = myDataSource.at(i);
columns = [];
for (var field in dataItem) {
if (dataItem.hasOwnProperty(field) &&
field != 'parent' &&
field != 'uid' &&
field != '_events') {
columns.push({
field: field,
value: dataItem[field.toString()]
});
}
}
columnsCount = columns.length;
for (var j = 0; j < columnsCount; j++) {
entryArray.push(dataItem[columns[j].field]);
}
rows.push(kendo.observable({
entries: entryArray
}));
}
var viewModel = kendo.observable({
gridRows: rows
});
3) At the end, I create a new Kendo UI grid with my definition of columns.
var finalColumns = [];
for (var k = 0; k <= columnsCount; k++) {
var entryIndex = "entries[" + k + "]";
if (k != columnsCount) {
finalColumns.push({
field: entryIndex,
title: columns[k].field
});
} else {
finalColumns.push({
command: [{
name: "CustomDelete",
text: "Delete",
className: "custom-delete-btn ",
imageClass: "k-icon k-i-close",
click: ManageDeleteButtonClick
}],
title: "Actions"
});
}
}
var configuration = {
editable: true,
sortable: true,
scrollable: false,
columns: finalColumns
};
function ManageDeleteButtonClick(e) {
e.preventDefault();
var dataItem = this.dataItem($(e.target).closest("tr"));
if (confirm('Are you sure you want to delete this record ?')) {
// AJAX CALL
var dataSource = $("#grid").data("kendoGrid").dataSource;
dataSource.remove(dataItem);
}
}
var myGrid = $("#grid").kendoGrid(configuration).data("kendoGrid");
kendo.bind($('#example'), viewModel);

Database driven Kendo Grid column

Is it possible to enumerate the grid columns eg (title and width) coming from a database table?
You will need to make an ajax call for that. Derive the column names from the table and then you can make modifications.
For e.g.
$.ajax({
url:actionUrl, //Url of the Method for fetching names of the columns and its count
success: function(result){
for (var i = 0; i < result.columnsCount; i++) { //running the loop based on number of columns needed
columns.push({
field: result.columnName, //set the columnNames from the Db as field
title: result.Header //specifying the columns title
});
}
}
});
You can try the following:
$(document).ready(function() {
var model = kendo.observable({
gridRows: []
});
var columns = [];
for (var i = 0; i < 4; i++) {
var entryIndex = "entries[" + i + "]";
columns.push({
field: i,
title: "Column " + i
});
}
var configuration = {
resizable: true,
columns: columns
};
var timeEditGrid = $("#grid").kendoGrid(configuration).data("kendoGrid");
kendo.bind($('#example'), model);
});
http://jsfiddle.net/4sM7g/

SlickGrid filter not working

I am fairly new to SlickGrid. I am trying to make SlickGrid filter work but no luck. I am following the example (http://mleibman.github.io/SlickGrid/examples/example4-model.html).
Below is my source code.
$(document).ready(function() {
var tName;
$('#submit').click(function(e) {
tName = $('#source option:selected').text();// name1
tName = tName.trim();
$.ajax({
url : 'someUrl',
type : 'GET',
cache : false,
success : function(d) {
var grid;
var searchString = "";
var data = [];
var columns = new Array();
var cols = d[0].columns;
var pkColNames = d[0].pkColNames;
for (var j=0; j< cols.length; j++) {
var key = {id: cols[j].colName, name: cols[j].colName, field: cols[j].colName, width: 200, sortable:true, editor: Slick.Editors.LongText};
columns[j] = key;
}
var options = {
editable: true,
enableAddRow: false,
enableCellNavigation: true,
asyncEditorLoading: false,
enableColumnReorder:true,
multiColumnSort: false,
autoEdit: false,
autoHeight: false
};
function myFilter(item, args) {
return true;// Let us return true all time ?
}
for (var i = 0; i < d.length; i++) {
var tempData = (data[i] = {});
var title = null;
var val = null;
for (var q = 0; q < d[i].columns.length; q++) {
title = d[i].columns[q].colName;
val = d[i].columns[q].colValue;
tempData[title] = val;
}
}
var dataView = new Slick.Data.DataView({ inlineFilters: true });
grid = new Slick.Grid("#myGrid", dataView, columns, options);
dataView.setPagingOptions({
pageSize: 25
});
var pager = new Slick.Controls.Pager(dataView, grid, $("#myPager"));
var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, options);
grid.setSelectionModel(new Slick.CellSelectionModel());
grid.onAddNewRow.subscribe(function(e, args) {
// Adding a new record is not yet decided.
});
grid.onCellChange.subscribe(function (e) {
var editedCellNo = arguments[1].cell;
var editedColName = grid.getColumns()[editedCellNo].field;
var newUpdatedValue= arguments[1].item[grid.getColumns()[editedCellNo].field];
var editedColType = "";
for (var cnt = 0; cnt < cols.length; cnt++) {
if (editedColName == cols[cnt].colName) {
editedColType = cols[cnt].colType;
break;
}
}
var pkKeyValue="";
for (var v=0; v <pkColNames.length;v++) {
for (var p=0; p<grid.getColumns().length; p++) {
if (pkColNames[v] == grid.getColumns()[p].field) {
var value = arguments[1].item[grid.getColumns()[p].field];
pkKeyValue += "{"+pkColNames[v] + '~' +getColDbType(grid.getColumns()[p].field) + ":"+value+"},";
break;
}
}
}
function getColDbType(colName) {
for (var c = 0; c < cols.length; c++) {
if (colName == cols[c].colName) {
return cols[c].colType;
}
}
}
pkKeyValue = pkKeyValue.substring(0, pkKeyValue.length-1);
$.ajax({
url: 'anotherUrl',
type:'GET',
dataType:'text',
success: function(f) {
bootbox.alert("Data updated successfully");
},
error: function() {
bootbox.alert("Error - updating data. Please ensure you are adding the data in right format.");
grid.invalidateAllRows();
grid.render();
}
});
});
grid.onClick.subscribe(function (e) {
//do-nothing
});
dataView.onRowsChanged.subscribe(function(e, args) {
grid.updateRowCount();
grid.invalidateRows(args.rows);
grid.render();
});
grid.onSort.subscribe(function(e, args) {
// args.multiColumnSort indicates whether or not this is a multi-column sort.
// If it is, args.sortCols will have an array of {sortCol:..., sortAsc:...} objects.
// If not, the sort column and direction will be in args.sortCol & args.sortAsc.
// We'll use a simple comparer function here.
var comparer = function(a, b) {
return a[args.sortCol.field] > b[args.sortCol.field];
}
// Delegate the sorting to DataView.
// This will fire the change events and update the grid.
dataView.sort(comparer, args.sortAsc);
});
// wire up the search textbox to apply the filter to the model
$("#txtSearch").keyup(function (e) {
console.log('Called...txtSearch');
Slick.GlobalEditorLock.cancelCurrentEdit();
// clear on Esc
if (e.which == 27) {
this.value = "";
}
searchString = this.value;
updateFilter();
});
function updateFilter() {
console.log("updateFilter");
dataView.setFilterArgs({
searchString: searchString
});
dataView.refresh();
}
dataView.beginUpdate();
dataView.setItems(data, pkColNames);
dataView.setFilterArgs({
searchString: searchString
});
dataView.setFilter(myFilter);
dataView.endUpdate();
},
error : function() {
bootbox.alert("Invalid user");
}
});
});
});
Your function myFilter() is always returning true so of course it will never work. The example that you looked at, was to filter something specific. I would recommend that you look at the following example to have a generic filter. From the example, simply type the text you are looking on a chosen column and look at the result... see example below (from SlickGrid examples).Using fixed header row for quick filters
In case you want a more in depth conditional filters ( > 10, <> 10, etc...), please take a look at my previous answer on how to make this kind of filtering possible, see my previous answer below:SlickGrid column type
Hope that helps you out

Kendo Ui Grid - dataItem.set() method not working properly

I have a grid with 4 columns name, age, collection, profit. But when I try to set a number column it's not reflecting on grid.
schema:
{
model:{
fields:{
name:{type:"string"},
age:{type:"number"},
collection: { type:"number", defaultValue:0.00},
profit: { type:"number", defaultValue:0.00}
}
}
}
This code works perfectly:
var grid = $("#grid").data("kendoGrid");
var data = grid.dataSource.at(0);
data.set("name", "John Doe");
But I want to update numeric column:
var grid = $("#grid").data("kendoGrid");
var data = grid.dataSource.at(0);
var collectionVal = 50000;
data.set("collection", collectionVal);
And it's not updating because the column is of type "number".
UPDATE:
pageable:
{
refresh : true,
pageSizes: true
},
edit: function(e)
{
$('input[name="age"]').blur(function()
{
mygrid = $("#grid").data("kendoGrid");
selectedRow = mygrid.select();
dataItem = mygrid.dataItem(selectedRow);
dataItem.collection = dataItem.age * dataItem.profit;
dataItem.set("collection", dataItem.collection);
});
}
Instead of updating collection in a blur handler defined in the edit, define a save event handler in your grid as follow:
pageable : {
refresh : true,
pageSizes: true
},
save : function (e) {
var profit = e.values.profit || e.model.profit;
var age = e.values.age || e.model.age;
this.dataSource.getByUid(e.model.uid).set("collection", age * profit);
}

With the Kendo UI Grid, how do you access the filtered and sorted data?

I have a Kendo grid that is sortable and filterable. When I export I want to export all the data that is currently viewable but not just the current page.
$("#grid").data("kendoGrid").dataSource -> seems to be the original list of items unsorted and unfiltered. In Chrome Developer tools, _data and _pristine seem to be the same.
There is also the dataSource.view but it is only the 10 items visible on the current page.
Is there a way to access the sorted list and/or filtered list?
update:
I have found this answer on the Kendo forums and will see if it helps.
http://www.kendoui.com/forums/framework/data-source/get-filtered-data-from-paged-grid.aspx
Here is how you access the filtered data:
var dataSource = $("#grid").data("kendoGrid").dataSource;
var filteredDataSource = new kendo.data.DataSource({
data: dataSource.data(),
filter: dataSource.filter()
});
filteredDataSource.read();
var data = filteredDataSource.view();
And then you can loop through the data:
for (var i = 0; i < data.length; i++) {
result += "<tr>";
result += "<td>";
result += data[i].SiteId;
result += "</td>";
result += "<td>";
result += data[i].SiteName;
result += "</td>";
result += "</tr>";
}
Most of the answers out there apply to the Kendo Grid when just looking at local data in memory. If you are using remote data (i.e. your grid is bound to an ODATA source for example) - you will need to iterate through all the pages to get the filtered data.
However, doing this was not as straight forward as I thought.
I came up with the following:
var filteredRows = [];
function getResults() {
var dataSource = $("#grid").data("kendoGrid").dataSource;
var filters = dataSource.filter();
var allData = dataSource.data();
var query = new kendo.data.Query(allData);
var data = query.filter(filters).data;
var totalRowCount = parseInt(dataSource.total().toString());
var totalPages = Math.ceil(totalRowCount / dataSource.pageSize());
PageTraverser(dataSource, 1, totalPages, filters, function () {
$('#pResults').text('Got ' + filteredRows.length + ' rows of filtered data.');
});
}
function PageTraverser(dataSource, targetPage, totalPages, filters, completionFunction) {
dataSource.query({
page: targetPage,
pageSize: 20,
filter: filters
}).then(function () {
var view = dataSource.view();
for (var viewItemId = 0; viewItemId < view.length; viewItemId++) {
var viewItem = view[viewItemId];
filteredRows.push(viewItem);
}
targetPage++;
if (targetPage <= totalPages) {
PageTraverser(dataSource, targetPage, totalPages, filters, completionFunction);
} else {
completionFunction();
}
});
}
Working example here: http://dojo.telerik.com/#JBoman32768/Ucudi
Here is how we are currently doing it, although there are multiple options:
var myData = new kendo.data.Query(dataSource.data()).filter(dataSource.filter()).data;
Your simply calling a new Query and applying the current filter that the grid has applied, which will return the exact same results as the grid.

Resources