How do you add dynamic queryParams to Backbone pageableCollection before syc - backbone.js

I am new to Backbone and I am trying to add extra parameter offset to queryParams before fetch sync occurs as the API does not support page, this is what I have tried to intercept the sync before sending options but it doesn't work, does anyone know how to achieve this?
Backbone.PageableCollection.extend({
model: Entities.Role,
url: function () {
return App.API + 'role';
},
mode: "server",
state: {
pageSize: 15,
order: 1,
firstPage: 1,
currentPage: 1
},
// You can remap the query parameters from `state` keys from
// the default to those your server supports
queryParams: {
offset: 0,
totalPages: null,
totalRecords: null,
sortKey: "sort",
pageSize: "max"
},
sync: function(method, model, options){
var defer = $.Deferred();
options.beforeSend=function(xhr) {
options.data.offset=(parseInt(model.state.currentPage) - 1) * model.state.pageSize;
model.queryParams.offset=(parseInt(model.state.currentPage) - 1) * model.state.pageSize;
defer.resolve(method, model, options);
}
return defer.promise(Backbone.sync(method, model, options));
}
});

solved:
you dont need to use defer - just works with:
sync: function(method, model, options){
options.data.offset=(parseInt(model.state.currentPage) - 1) * model.state.pageSize;
model.queryParams.offset=(parseInt(model.state.currentPage) - 1) * model.state.pageSize;
return Backbone.sync(method, model, options);
}

Related

How to use Angular Js ajax with dx-scheduler

I am using dx-scheduler calendar and i'm trying to use crud operations for the meetings. I wonder how can i use functions in DevExpress.data.AspNet.createStore instead of their own api methods - here is an example of their API :
DevExpress.data.AspNet.createStore({
key: "AppointmentId",
loadUrl: url + "/Get",
insertUrl: url + "/Post",
updateUrl: url + "/Put",
deleteUrl: url + "/Delete",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
I want to achieve this :
DevExpress.data.AspNet.createStore({
key: "AppointmentId",
loadUrl: function(){
$http.get("/getApi").then(function(){
// manipulate the fetched data
})
},
insertUrl: : function(values){
// manipulate the values before post
$http.post("/getApi", values).then(function(){
}),
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
Example.
According to Documentation in this link
loadUrl - the URL used to load data. I assume that you should pass the URL string here for your get api.
if parameters is needed for your get request you can send them using LoadParams Option
loadParams - additional parameters that should be passed to loadUrl.
and handle the result by implementing the onLoaded ..
onLoaded - refer to CustomStore.onLoaded.
$scope.schedulerOptions = {
dataSource: DevExpress.data.AspNet.createStore({
key: "AppointmentId",
// loadUrl: 'https://jsonplaceholder.typicode.com/posts',
loadUrl: "https://jsonplaceholder.typicode.com/posts",
insertUrl: url + "/Post",
updateUrl: url + "/Put",
deleteUrl: url + "/Delete",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
onLoaded:function(result){
console.log(result)
var data = result;
for (var i in data) {
data[i].StartDate = '2020-12-20T10:00:00Z';
data[i].EndDate = '2020-12-20T11:00:00Z';
}
return data;
}
}),
// remoteFiltering: true,
dateSerializationFormat: "yyyy-MM-ddTHH:mm:ssZ",
views: ["day", "workWeek", "month"],
currentView: "day",
currentDate: new Date(),
startDayHour: 9,
endDayHour: 19,
height: 600,
textExpr: "title",
startDateExpr: "StartDate",
endDateExpr: "EndDate",
allDayExpr: "AllDay"
};
The result from the get request is printed in the console in the onLoaded function
The data you are using in your example in this json
https://jsonplaceholder.typicode.com/posts
Does not contain EndDate , maybe if you modified it to include Start Date and EndDate with the same dateSerializationFormat it will work, I modified them manually and it worked, I also modified textExpr to display title.
your Example link modified
In order to use your own Ajax request , you can use the following work around, Initialize the schedulerOptions after you do your Ajax call using the result as data resource. Example link
Html :
<div class="dx-viewport demo-container" ng-app="DemoApp" ng-controller="DemoController">
<div dx-scheduler="schedulerOptions" ng-if=dataSet></div>
</div>
JS:
$scope.dataSet;
var loadFromUrl = function () {
$http.get('https://jsonplaceholder.typicode.com/posts')
.then(function(result){
$scope.dataSet = result.data;
for (var i in $scope.dataSet) {
$scope.dataSet[i].startDate = '2020-12-20T10:00:00Z';
$scope.dataSet[i].endDate = '2020-12-20T11:00:00Z';
}
$scope.schedulerOptions = {
dataSource: $scope.dataSet,
dateSerializationFormat: "yyyy-MM-ddTHH:mm:ssZ",
views: ["day", "workWeek", "month"],
currentView: "day",
currentDate: new Date(),
startDayHour: 9,
endDayHour: 19,
height: 600,
textExpr: "title",
startDateExpr: "startDate",
endDateExpr: "endDate",
allDayExpr: "AllDay"
};
})
};
loadFromUrl();

How to use openlayers getUrl function in new ImageWMS?

I am using OpenLayers in my reactjs project. As per the documentation
I have tried the following code
var sourceData = new ImageWMS(
{
params: {'LAYERS': 'top:states'},
ratio: 1,
serverType: 'geoserver',
getURL: function () {
console.log('bounds');
}
});
this.olmap = new Map({
target: null,
layers: [new ImageLayer({
extent: [-13884991, 2870341, -7455066, 6338219],
source: sourceData
})],
view: new View({
center: this.state.center,
zoom: this.state.zoom
})
});
I am trying the above code but it is not showing console log.
Can I know how to make it work so that I can get the console log?
It simply returns the url used to construct the source, e.g.
var sourceData = new ImageWMS(
{
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'top:states'},
ratio: 1,
serverType: 'geoserver'
});
console.log(sourceData.getURL()); // 'https://ahocevar.com/geoserver/wms'
To log the full url or its query string parameters you would need to customise the imageLoadFunction
var sourceData = new ImageWMS(
{
url: 'https://ahocevar.com/geoserver/wms',
params: {'LAYERS': 'top:states'},
ratio: 1,
serverType: 'geoserver',
imageLoadFunction: function(image, src) {
var params = new URLSearchParams(src.slice(src.indexOf('?')));
console.log('bounds', params.get('BBOX'));
image.getImage().src = src;
}
});

ExtJS 4: Ext.grid.Panel Ext.PagingToolbar buttons (first, previous, next, last) not passing start and limit parameters

I'm having difficulty getting the paging toolbar to work. The initial load passes the "start" and "limit" parameter to the server proxy and the data loads fine in the grid. However, when clicking the "Next" button in the paging toolbar, the "start" and "limit" parameters don't get passed properly and the web method bombs out because it expects those parameters. If you can help me fix the root problem, that would be awesome. But if not, and you're able to help me override the buttons, that's also fine, so I can put in a temporary fix until I figure out what's wrong.
Exception:
POST http://{domain}/Controls/ObjectList/ObjectListService.asmx/GetObjectList?_dc=1348591244365 500 (Internal Server Error) ext-all-debug.js:36837
Ext.define.request ext-all-debug.js:36837
Ext.define.doRequest ext-all-debug.js:49508
Ext.define.read ext-all-debug.js:39082
Ext.define.load ext-all-debug.js:47668
Base.implement.callParent ext-all-debug.js:3728
Ext.define.load ext-all-debug.js:50160
Ext.define.read ext-all-debug.js:47399
Ext.define.loadPage ext-all-debug.js:50404
Ext.define.nextPage ext-all-debug.js:50409
Ext.define.moveNext ext-all-debug.js:102105
Ext.define.fireHandler ext-all-debug.js:79530
Ext.define.onClick ext-all-debug.js:79520
(anonymous function)
Ext.apply.createListenerWrap.wrap ext-all-debug.js:9171
{"Message":"Invalid web service call, missing value for parameter: \u0027query\u0027.","StackTrace":" at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
===========================
Source Code:
var itemsPerPage = 30;
var store = new Ext.data.Store({
proxy: new Ext.ux.AspWebAjaxProxy({
url: '/Controls/ObjectList/ObjectListService.asmx/GetObjectList',
actionMethods: {
create: 'POST',
destroy: 'DELETE',
read: 'POST',
update: 'POST'
},
reader: {
type: 'json',
model: 'Object',
totalProperty: 'd.recordCount',
//idProperty: 'object_id',
root: 'd.resultSet'
},
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}),
pageSize: itemsPerPage,
noCache: false,
//autoLoad: true
autoLoad: {
params: {
//query: '',
start: 0,
limit: itemsPerPage
}
}
});
...
Ext.define('ObjectGrid', {
extend: 'Ext.grid.Panel',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
store: store,
forceFit: true,
autoScroll: true,
height: 750,
loadMask: true,
columns: [
],
...
bbar: Ext.create('Ext.PagingToolbar', {
store: store,
displayInfo: true,
pageSize: 30,
displayMsg: 'Displaying records {0} - {1} of {2}',
emptyMsg: 'No records to display'
// type: 'pagingmemory',
// listeners: {
// afterrender: {
// single: true,
// fn: function (thispaging) {
// thispaging.first.on('click', function () {
// Ext.Msg.alert('first', 'first');
// });
// thispaging.prev.on('click', function () {
// Ext.Msg.alert('prev', 'prev');
// });
// thispaging.next.on('click', function () {
// Ext.Msg.alert('next', 'next');
// });
// thispaging.last.on('click', function () {
// Ext.Msg.alert('last', 'last');
// });
// }
// }
// }
// listeners: {
// 'click' : function(which) {
// alert('you have clicked');
// }
// }
}) // bbar
});
me.callParent(arguments);
}
});
update #1:
The parameters are being lost between these two calls in the stack trace mentioned above.
line 39082:
this.requests.5.options.params = "{}"
(5) being the current object
line 47668:
operation.start = 2
operation.limit = 30
update #2:
Ext.define('Ext.ux.AspWebAjaxProxy', {
extend: 'Ext.data.proxy.Ajax',
require: 'Ext.data',
//processData: false,
buildRequest: function (operation) {
var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
request;
params = Ext.applyIf(params, this.getParams(params, operation));
if (operation.id && !params.id) {
params.id = operation.id;
}
params = Ext.JSON.encode(params);
request = Ext.create('Ext.data.Request', {
params: params,
action: operation.action,
records: operation.records,
operation: operation,
url: operation.url
});
request.url = this.buildUrl(request);
operation.request = request;
return request;
}
});
Well I guess the trick lies within
// Clone params right now so that they can be mutated at any point further down the call stack
var me = this,
params = operation.params = Ext.apply({}, operation.params, me.extraParams),
request;
I think you can use this to replace your first lines, I guess it should work then.
Please look also at
// Set up the entity id parameter according to the configured name.
// This defaults to "id". But TreeStore has a "nodeParam" configuration which
// specifies the id parameter name of the node being loaded.
if (operation.id !== undefined && params[me.idParam] === undefined) {
params[me.idParam] = operation.id;
}
dunno if you need to update this too.
I tried going back to ExtJS version 4.0.0, but other features in my application are breaking. So I'm sticking with version 4.1.0 and implemented a hack for this proxy so it'll work, so I can have some piece of mind (or is it "peace of mind?").
Ext.define('Ext.ux.AspWebAjaxProxy', {
extend: 'Ext.data.proxy.Ajax',
require: 'Ext.data',
buildRequest: function (operation) {
var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
request;
params = Ext.applyIf(params, this.getParams(params, operation));
if (params.page == null) {
params.page = operation.page;
params.start = operation.start;
params.limit = operation.limit;
}
if (operation.id && !params.id) {
params.id = operation.id;
}
params = Ext.JSON.encode(params);
request = Ext.create('Ext.data.Request', {
params: params,
action: operation.action,
records: operation.records,
operation: operation,
url: operation.url
});
request.url = this.buildUrl(request);
operation.request = request;
return request;
}
});
//});

Ext.data.HttpProxy callback on failure

I've the following ExtJS. The listener "write" is called when the response is a success (the response is JSON like: {"success":true,"message":"......"}). But how do I attach a callback when the response is not a success? ({"success":false,"message":"......"})
tableStructure.proxy = new Ext.data.HttpProxy({
api: {
read: '/controller/tables/' + screenName + '/getstructure/' + table,
create: '/controller/tables/' + screenName + '/createcolumn/' + table,
update: '/controller/tables/' + screenName + '/updatecolumn/' + table,
destroy: '/controller/tables/' + screenName + '/destroycolumn/' + table
},
listeners: {
write: tableStructure.onWrite
}
});
You want to catch the HttpProxy's exception event.
listeners: {
write: tableStructure.onWrite
exception: function(proxy, type, action, options, response, arg) {
if(type === 'remote') { // success is false
// do your error handling here
console.log( response ); // the response object sent from the server
}
}
}
You can find the full documentation in the Ext docs for Ext.data.HttpProxy down in the events section.
You should be able to make use of the write event itself. The write event's signature is:
write(dataproxy,action,data,response,record,options).
You can access the success variable from the action object and check if the value is true or false. You should be able to access the success variable as:
action.result.success
You can do:
if(action.result.success != true ) {
// If success is not true
} else {
// If success is true
}
You can also set an exception handler on the Ext.data.Store wrapping the HttpProxy, provided that you send a response code other than 200.
var store = new CQ.Ext.data.Store({
proxy : new CQ.Ext.data.HttpProxy({
method : "GET",
url : '/some_url'
}),
reader : new CQ.Ext.data.JsonReader(),
baseParams : {
param : 'some value'
}
});
store.on("beforeload", function() {
CQ.Ext.getBody().mask("Please wait...", false);
});
store.on("exception", function() {
CQ.Ext.getBody().unmask();
CQ.Ext.Msg.show({
title: 'Error',
msg: '<span style="color:red">Bad request.</span><br/>',
icon: CQ.Ext.Msg.ERROR,
buttons: CQ.Ext.Msg.OK
});
});

persisting filters in grid panel

I would like to persist filters applied on gridpanel on page refresh. Can you please guide me in doing this.
Thanks.
Here is the code which send the filter data to webservice
Ext.extend(Ext.ux.AspWebServiceProxy, Ext.data.DataProxy,
{
load: function(params, reader, callback, scope, arg) {
var userContext = {
callback: callback,
reader: reader,
arg: arg,
scope: scope
};
var proxyWrapper = this;
//debugger;
//Handles the response we get back from the web service call
var webServiceCallback = function(response, context, methodName) {
proxyWrapper.loadResponse(response, userContext, methodName);
}
var serviceParams = [];
var filters = {};
//Convert the params into an array of values so that they can be used in the call (note assumes that the properties on the object are in the correct order)
for (var property in params) {
if (property.indexOf("filter[") == 0) {
filters[property] = params[property];
}
else {
serviceParams.push(params[property]);
}
//console.log("Property: ", property, "Value: ", params[property]);
}
serviceParams.push(filters);
//Add the webservice callback handlers
serviceParams.push(webServiceCallback);
serviceParams.push(this.handleErrorResponse);
//Make the actual ASP.Net web service call
this.webServiceProxyMethod.apply(this.webServiceProxy, serviceParams);
},
handleErrorResponse: function(response, userContext, methodName) {
window.location.reload();
// Ext.MessageBox.show({
// title: 'Error',
// msg: response.get_message(),
// buttons: Ext.MessageBox.OK,
// icon: Ext.MessageBox.ERROR
// });
//alert("Error while calling method: " + methodName + "n" + response.get_message());
},
loadResponse: function(response, userContext, methodName) {
var result = userContext.reader.readRecords(response);
userContext.callback.call(userContext.scope, result, userContext.arg, true);
}
});
Turn on the Ext JS state manager globally (where you set Ext.BLANK_IMAGE_URL).
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
User changes to some components will now be stored in a cookie, which will persist across requests. If you need to store additional custom data, you can do that using Ext.state.Manager.set and Ext.state.Manager.get. State is configurable on individual components.
Saki has a good example.
To persist filters on grid you can use cookies, here you can find some help:
proxy: new Ext.data.HttpProxy({
url: (local ? url.local : url.remote),
method: 'GET',
listeners:{
beforeload : function(dataproxy,param) {
if(param.searchConditions != undefined && param.searchConditions != '[]') {
Ext.util.Cookies.set('SearchConditions',param.searchConditions);
}
}
}
})
In above sample you can find that we are setting "searchConditions" JSONArray in cookies.Now let us see how to get back that "searchCondition" whenever you load you Grid.
store.load({
params:{
start:0,
limit: 50,
searchConditions:JSON.parse(Ext.util.Cookies.get('SearchConditions'));
}
});
Here simply you just need to pass your "searchCondition" parameter value as value stored in Cookie. Hope above example is useful.Please comment for any help.

Resources