Kendo Grid Server Side filtering sending null as a filter object to the backend - angularjs

Using Kendo AngularJS and ASP .NET MVC I am trying to send the filters object of a grid to the backend. However any filters made on the frontend are null in the request even though I set serverFiltering to true.
grid.dataSource = new kendo.data.DataSource({
serverFiltering: true,
transport: {
read: {
url: "api/foo",
dataType: "json",
type: "POST"
}
},
schema: {
data: "data", // records are returned in the "data" field of the response
total: "total"
}
});
//set grid to filterable
grid.filterable = {
mode: 'row',
operators: {
string: {
contains: "contains"
}
}
};
I took a look at a similar question but it did not help me as I wasn't able to replicate the solution listed as the accepted answer

On the controller side the "DataSourceRequest" mapped out the form values differently (e.g. inspecting the POST request on the frontend sent "filter" instead of "Filters" as an argument. I had to create a new model class that binded the proper values

Related

Select2 custom data fetch when user starts typing in search bar. (BackboneJS / Marionette collection) SELECT2

I am using SELECT2 in BackboneJS/Marionette. Right now following is flow:
Current:
From parent, call FETCH method of COLLECTION. When fetch is completed then send this COLLECTION to a new VIEW and display drop down (SELECT2)
New Requirement:
Now need to convert this data fetch at run-time. When user types in search bar of SELECT2, ajax call should be made and returned data needs to be converted to Marionette collection and then rendered in drop-down.
For this, i tried to implement this example.
Now problem is that data is fetched (visible in network tab), but drop-down remains empty (and there is no error/exception):
Added following code in _SELECTOR.prototype.settings.extend
ajax: {
url: API_PATH + "testingvalues2",
dataType: 'json',
delay: 1000,
minimumInputLength: 1,
cache: true,
data: function (params) {
var query = {
filter: params.term
};
console.log("query: ", query);
return query;
},
processResults: function (data) {
console.log("data : ", data);
console.log("this>>", this);
let newCollection = new DropdownDataCollection();
for(let dataItem of data){
let item = new DropdownValueEntity (dataItem);
newCollection.add(item);
}
return {results : newCollection};
}
},

How to prevent Kendo MultiSelect from losing values after editing in a grid template?

I have a grid that displays a comma-separated list of values, and it has an array that gets used in a template editor for the grid. (On the server, I transform the comma-separated list to an array for the Kendo multiselect AngularJS directive). I have almost everything working: display, edit, and adding values in the multiselect.
There's just one weird thing happening: after I add a value in the multiselect, click Save in the editor, and reopen the editor, the multiselect then only displays one of the most-recently entered values. I know that the values are there and going through the pipeline, because the values make it into the database. I can refresh the page, open the editor, and all the values display in the multiselect correctly, including the one I just added.
It's as if kendo "forgets" most of the values when I reopen the editor. How can this be prevented? Does the MultiSelect need to be rebound to the values? If so, how?
I have tried adding this onChange event, but it had no effect. I've added valuePrimitive to no effect. I tried specifying k-rebind, but it caused an error.
Here's the directive being used in the text/x-kendo-template:
<select kendo-multi-select
id="zipCode"
k-placeholder="'Enter zip codes...'"
style="width: 225px"
k-on-change="dataItem.dirty=true"
k-auto-bind="false"
k-min-length="3"
k-enforce-min-length="true"
k-data-source="options.zipCodeDataSource"
k-data-text-field="'text'"
k-filter="'startsWith'"
k-filtering="options.zipCodeFiltering"
k-no-data-template="'...'"
k-ng-model="dataItem.zipArray"
k-highlight-first="true" />
And this is the DataSource:
options.zipCodeDataSource = new kendo.data.DataSource({
severFiltering: true,
transport: {
read: {
url: serviceUrl + "ZipCode/Get",
type: "GET",
dataType: "json",
contentType: jsonType,
data: function (e) {
// get your widget.
let widget = $('#zipCode').data('kendoMultiSelect');
// get the text input
let filter = widget.input.val();
// what you return here will be in the query string
return {
filter: filter
};
}
},
},
schema: {
data: "data",
total: "Count",
model:
{
id: "text",
fields: {
text: { editable: false, defaultValue: 0 },
}
},
parse: function (response) {
return response;
}
},
error: function (e) {
}
});
If I display {{dataItem.zipArray}} in a <pre> all of the expected values are there.
I wonder if something needs to be added to the edit event handler in the kendo grid definition, but I'm not sure what it would be. I've had to do binding like that for the dropdownlist directive.
edit: function (e) {
if (e.model.marketId === 0) {
e.container.kendoWindow("title", "Add");
} else {
e.container.kendoWindow("title", "Edit");
}
// re-bind multi-select here??
// These two lines actually cause the multiselect to lose pre-existing items in dataItem.zipArray
// var multiselect = kendo.widgetInstance(angular.element('#zipCode'));
// multiselect.trigger('change');
}
...
Update:
This dojo demonstrates the issue.
Run the dojo
Edit the first record in the Contracts grid
Add a zip code such as 22250
Click Save
Then click Edit on the first row again
Only zip code 22250 is displayed in the editor
Also, I notice that if I change k-min-length="3" to k-min-length="1", then the issue goes away. But in the scenario I'm working on, it needs to be 3.
This seems to be an issue with kendo itself. Back then this issue was reported here.
Ok based on the reply from telerik, this issue has been fixed in 2017 R3 SP1 release (2017.3.1018). You can verify it by using this updated dojo example:
http://dojo.telerik.com/IREVAXar/3

ExtJS 4 Store's filterBy() affect only first page when pagingmemory proxy is used

I have a grid and its store configured with Ext.ux.data.PagingMemoryProxy, like this:
Ext.create('Ext.data.Store', {
data: myData,
fields: storeFields,
proxy: {
type: 'pagingmemory',
reader: {
type: 'array',
getData: function(rawData) {
...
},
}
},
remoteFilter: true,
remoteSort: true
});
When I want to filter store locally I use either filter() or filterBy().
When I use filter() full set of data is filtered (passed via data: myData), but when I use filterBy() its only affect first page.
Is it possible to apply a filterBy() to the entire data set in similar way with filter() when pagingmemory proxy is used?
I understand that pagingmemory proxy use two stores to save the entire data and data to be used in grid store, and I understand that it is possible to rewrite filterBy() work, but perhaps there is some simple solution?

this.proxy is undifened EXT JS paging

I have a store :
var store = new Ext.data.JsonStore({
root: 'list',
fields: rec,
totalProperty:'totalCount',
pruneModifiedRecords:true
});
And want to do paging.
my paging toolbar :
var paging = new Ext.PagingToolbar({
pageSize : limit,
width : 600,
store : store,
displayInfo : true,
displayMsg : 'Total: {2}, (Show:{0}-{1})',
emptyMsg : "No data"
});
and my grid :
var grid = new Ext.grid.EditorGridPanel({
region:'center',
stripeRows: true,
frame: false,
border:false,
loadMask: {msg : 'Loading...'},
trackMouseOver:false,
store: store,
cm: cm,
sm: sm,
tbar:gridTbar,
bbar: paging,
viewConfig: {enableRowBody:true,emptyText: 'no data'}
});
And when button pressed load data from database :
var limit= 100;
function storeDoldur(){
Ext.Ajax.request({
url: '../project/listData.ajax',
params:{
date:date.getRawValue(),
start:0,
limit:limit
},
success:function(response,options){
var res= Ext.decode(response.responseText);
if(res.success){
store.loadData(res);
grid.getView().refresh();
grid.doLayout();
}
else{
Ext.MessageBox.alert("result",res.message);
}
globalMask.hide();
},
failure: function(response,options) {
globalMask.hide();
Ext.MessageBox.alert(error);
}
});
}
Here is the problem :
Total count is 108. First 100 resut is showing with success but when i press next page button ext says :
TypeError: this.proxy is undefined
...ueUrl(this.proxy,e)){c.params.xaction=e}this.proxy.request(Ext.data.Api.actions[...
How can fix this problem?
Edit :
var store = new Ext.data.JsonStore({
root: 'list',
**url: '../project/listData.ajax',**
fields: rec,
totalProperty:'totalCount',
pruneModifiedRecords:true,
autoLoad : false,
});
ajax request post this params : date,start,limit
I click second page button, in backend code database returns null because of date is null. Second page request params are start and limit values. Don't send date parameter??
In order for the paging toolbar to work, your store must be configured with a proxy with a url property, so that when you click the next\previous button on the toolbar the store can fetch the required page of data from the server.
In your code, your are making a separate Ajax request and so your store has no idea about the url to use for fetching the next page.
Take a look at the example here => http://docs.sencha.com/extjs/4.2.0/#!/example/grid/paging.html and look at the paging.js source code linked to at the top of that page. That should give you enough to proceed.
You should also listen to the store load event to handle the successful fetch of data.
EDIT
For ExtJS 3 you should make use of baseParams in your store config object (http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.Store-cfg-baseParams). You can also set these dynamically, so in your case in your storeDoldur function rather than the Ajax approach you would do something like this:
var limit= 100;
function storeDoldur(){
store.setBaseParam('date', date.getRawValue());
store.load({
params: {
start: 0,
limit: limit
},
callback: function() {
}
});
}
Again, do not use an Ajax request, instead use a properly configured store with a proxy as that's what the paging toolbar expects in order to work properly. In the edit above, setting an extra base parameter is necessary so it gets passed in subsequent request when using the paging toolbar next\previous buttons.
Notice when calling load on the store, I have added an empty stub for a callback function which you can use to handle the response further when its returned back from the server - http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.data.Store-method-load
You wont need to use the code in your success handler from the Ajax request you originally used, since loading data (including other pages using the paging toolbar) into the store will cause the grid to update automatically.

ExtJS 4.2: Multiple Inserts

Ok, so say I have a store server side so we are doing remote everything. Example of stores:
Ext.create('Ext.data.Store', {
model: 'MyApp.model.ContactModel',
remoteFilter: true,
remoteSort: true,
autoLoad: true,
autoSync: true,
storeId: 'ContactStore-1'
});
Ext.create('Ext.data.Store', {
model: 'MyApp.model.ContactModel',
remoteFilter: true,
remoteSort: true,
autoLoad: true,
autoSync: true,
storeId: 'ContactStore-2'
});
I hit a problem when I do the following:
Ext.getStore('ContactStore-1').insert(0,{'name':'say'});
Ext.getStore('ContactStore-2').insert(0,{'name':'hi'});
What happens is that when I look at the DB I end up having 2 entries. I get 'hi' once and 'say' twice. From the looks of it what is happening is that the first insert statement gets sent and then the second insert statement gets sent but with data from both inserts (I assume it's cause they share the same model and thus the same proxy)
Thoughts on how I can resolve this so that it doesn't auto merge insertion requests?
Model for your viewing pleasure:
Ext.define('MyApp.model.ContactModel', {
extend: 'Ext.data.Model',
idProperty: 'idContact',
fields: [
{
name: 'idContact',
type: 'int'
},
{
name: 'name',
type: 'string'
}
],
proxy: {
type: 'direct',
api: {
create: contact.createRecord,
read: contact.getResults,
update: contact.updateRecords,
destroy: contact.destroyRecord
},
reader: {
type: 'json',
root: 'data'
}
}
});
I think you are not returning the correct data from the server side on the create. If you do not return the id the server created on the first insert, ExtJS will still think your "say" item is a phantom. That is, it has not yet been stored server side.
When you do the second insert, the store will do a sync as you have autosync on. Sync will send ALL pending changes. Since your "hi" item is new that will be sent in a POST as is expected. But since your previous "hi" item does not have a server generated id and is still a phantom, it too will be sent in a POST with your second sync (triggered by the insert).
Basically the server must return the new id with the success result set so that ExtJS knows that the item has been stored by the server. Here's an example from my REST API:
Request has this payload (check Chrome Developer tools network tab).
POST to http://localhost:8081/api/channel?_dc=1372594759864
{"id":0,"number":0,"name":"test"}
This is the server response (200 OK):
{
"result": {
"id": 4, // <- important
"number": 3,
"name": "test",
},
"success": true,
"location": "http://localhost:8081/api/item/4",
"userMessage": null,
"userTitle": "Success",
"devErrors": null
}
All fields in the model are updated by the data in the server response, and as such your hi and say items will get their server id's set. When the id is set, the phantom property is set to false. You can have a look in the Ext.data.Model js-file for the source code for this if you want to dig deeper. :)
In your case you must have idContact in the returned object as that is you idProperty.
If you want to suspend auto sync, do your inserts and sync manually and then turn auto syncs back on you can use SuspendAutoSync and ResumeAutoSync.
The best way to add models to stores in my opinion is to create your model, save it, and on success put it in the store. That requires you to have the proxy in each model. That would look something like this:
var hi = Ext.create('MyApp.model.ContactModel', {
name: 'hi'
});
hi.save({
success: function (record, operation) {
Ext.getStore('ContactStore-1').add(hi);
// You could do your second insert here that is dependent on the first to be completed
},
failure: function (record, operation) {
Ext.MessageBox.alert("Error", "Could not save model at this time...");
},
scope: this
});
In this way you could add your second item in the success handler of the first item's save.

Resources