Jqgrid custom form and custom function - jqgrid

I have the following problem. I m using a custom form for Jqgrid, the problem is that I can t figure it out how can I use different functions for submit button in add/edit/delete. Can you help me? I can use delfunc with succes. How can I add delfunc to the button submit from del form, and the function addfunc to submit button from the form of add.
$('#jqGrid').navGrid("#jqGridPager", {
edit: true,
add: true,
del: true,
refresh: true,
view: false,
addfunc : function(){
var angajat = new Object();
angajat.id = null;
angajat.firstName = "andrei" //jQuery("#jqGrid").jqGrid('getRowData');
angajat.lastName = " chivu " //jQuery("#jqGrid").jqGrid('getRowData');
console.log(angajat);
$.ajax({
type: "POST",
url: "rest/user/add",
data: JSON.stringify(angajat),
contentType: "application/json; charset=utf-8",
dataType: "json",
contentType: "application/json",
success: function (data) {
$("#response").html(JSON.stringify(data));
}
});
},
delfunc : function (id){
$.ajax({
type:"DELETE",
url:"rest/user/delete",
data:JSON.stringify(id),
dataType: "json",
contentType: "application/json",
}).done(function( msg ) {
alert("Content Deleted: " + id);},
jQuery("#jqGrid").trigger("reloadGrid"));
},
editCaption: "Update Employee",
template: template,
//onClick: alert("alaaaaa"),
errorTextFormat: function (data) {
return 'Error: ' + data.responseText
}
},
// options for the Add Dialog
{
addCaption: "Add new Employee",
template: template,
sData: alert("alaaaaa"),
errorTextFormat: function (data) {
return 'Error: ' + data.responseText
}
},
// options for the Delete Dialog
{
caption: "Delete the Employee",
msg: "Are you sure ? ",
beforeSubmit: alert("alaaaaa"),
errorTextFormat: function (data) {
return 'Error: ' + data.responseText
},
});
});

One don't need to use delfunc, addfunc, editfunc or viewfunc in the most cases. The function are replacements for delGridRow, editGridRow and viewGridRow, but to replace the methods which code is not so small one have to understand the code in details.
I try to explain your problem how I understand it. I'll start with the usage of delfunc. What you try to do is calling of URL rest/user/delete using HTTP DELETE. Thus I suppose that you have RESTful services on the backend. To use HTTP DELETE you need to append the id of deleted item to the URL, use DELETE operation and be sure that no other information (like oper parameter) are placed in HTTP body. Thus you can use existing options of delGridRow.
It's important to understand that navGrid just add some buttons in the navigator bar and it calls the methods delGridRow, editGridRow and viewGridRow if the user clicks on the corresponding buttons. The options of navGrid looks like
$("#gridid").jqGrid('navGrid','#gridpager', {parameters},
prmEdit, prmAdd, prmDel, prmSearch, prmView);
(see the documentation). The parameters parts are real options of navGrid and it informs navGrid for example which buttons should be included on the navigator bar. The other options are the options of delGridRow, editGridRow, searchGrid and viewGridRow methods which shoule be used if the user clicks on the corresponding button of navigator bar. To configure the behavior of Delete button we need to specify prmDel parameter. The value of the parameter should be object with the properties and
callbacks of delGridRow method. See the documentation.
In the same way if one uses formatter: "actions" or inlineNav then another buttons will be added and one have to use the corresponding options to specify, which options of delGridRow should be used.
I find that the options of navGrid is difficult to understand. Because of that I introduced in free jqGrid alternative way of specify default options used in jqGrid by delGridRow inside of formDeleting of jqGrid options. Thus the most free jqGrid looks like the demo. It uses formEditing, formViewing, searching options of jqGrid and the call of navGrid is either without any parameters or with the small set of options. Now back to your main problems. See the wiki for more information.
If the main logic is clear then it will be clear how one configure jqGrid to do on Delete exactly what you need. To do this you should specify mtype: "DELETE" option and ajaxDelOptions: {...} to specify other options of Ajax call. To append the id to the URL you can use onclickSubmit or beforeSubmit callbacks (see the answer), but in free jqGrid and can use url defined as function (see the answer) and have more readable code. Thus I suggest you to use formDeleting option with the value
{
mtype: "DELETE",
url: function (rowid) {
return "/rest/user/delete/" + rowid;
},
ajaxDelOptions: { contentType: "application/json" },
serializeDelData: function () {
return "";
},
reloadGridOptions: { fromServer: true },
}
The grid will be reloaded automatically on successful deleting because reloadAfterSubmit: true is default option of delGridRow (see here). The last option reloadGridOptions is helpful in case of usage loadonce: true option of jqGrid. It will force reloading of grid from the server.
In the same way to configure Add and Edit buttons you can use formEditing option of jqGrid with the value
{
url: function (id, editOrAdd) {
return "/rest/user/" + (editOrAdd === "add" ? "add" : "edit");
},
mtype: function (editOrAdd) {
return editOrAdd === "add" ? "POST" : "PUT";
},
serializeEditData: function (postData) {
return JSON.stringify(postData);
},
serializeEditData: function (postData) {
var dataToSend = $.extend({}, postData); // make copy of data
// don't send any id in case of creating new row or to send `0`:
if (dataToSend.id === "_empty") {
delete dataToSend.id; // or dataToSend.id = 0;
}
return JSON.stringify(dataToSend);
},
ajaxEditOptions: { contentType: "application/json" },
reloadGridOptions: { fromServer: true }
}

Related

how to? with knockout js validations

I've started using knockout js validations with http://ericmbarnard.github.com/Knockout-Validation/ validation engine, and I'm not clear as to how to do the following:
1) Say I want to set a particular field required based on a condition. How do I do that?
e.g.
this.Username = ko.observable().extend({ required: true }); // make required = true only if this.UserType = 2, etc...
2) I've got the validation messages firing right next to the field being validated. I want only an '*' to appear next to the field and display the error messages in a validationsummary field at the bottom of the page. All validation errors should display there. How to do that?
3) The form submit to be avoided until the form validation is passed. Rightnow, I get the validation error messages, still the form gets submitted. So I guess I'm doing something wrong. Following is my code:
$(document).ready(function () {
var model;
// enable validation
ko.validation.init();
$.ajax({
type: "POST",
url: SERVER_PATH + '/jqueryservice/DataAccessService.asmx/GetData',
async: false,
data: "{ }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result, status) {
model = new ViewModel(result);
ko.applyBindings(model);
},
error: GetDataError
});
$('#submit').click(function () {
var data = ko.toJS(model);
delete data.Vehicles;
delete data.CopyWeeks;
delete data.SetupTotal;
delete data.CloseTotal;
var mappedItems = ko.utils.arrayMap(data.DailyItemList, function (item) {
delete item.Add;
delete item.Delete;
return item;
});
data.DailyItemList = mappedItems;
$.ajax({
type: "POST",
url: SERVER_PATH + '/jqueryservice/DataAccessService.asmx/ProcessData',
async: false,
data: ko.toJSON(data),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result, stat) {
alert(success);
return false;
},
error: function (e) {
alert(e);
}
});
});
});
Thanks in advance for your help.
EDIT:
I've seen that I can set the validation configuration as follows:
ko.validation.configure({
decorateElement : false,
errorMessageClass: 'errorMsg',
insertMessages : false,
parseInputAttributes : true,
messageTemplate: 'sErrorMsg'
});
ko.validation.init();
but I'm not sure how I can define my error message template 'sErrorMsg'
1). Say I want to set a particular field required based on a condition....
For this ko validation contains a native rule. You can do something like :
var myObj = ko.observable().extend({ required: {
onlyIf: function() {
//here you can place your codition and can return..
//true or false accordingly
}
}});
2). I've got the validation messages firing right next to the field being validated..
For this you should check Validation Binding. In this validationOptions can do the job for you.
Update: here's a fiddle which demonstrate the use of messageTemplate binding as per your requirement.
http://jsbin.com/ocizes/3/edit
3). The form submit to be avoided until the form validation is passed....
For this you can use use group , like :
yourViewModel.Errors = ko.validation.group(yourViewModel);
Now the Errors property contains the error messages of your observables, if any. So before submitting the form you can put check something like :
if(yourViewModel.Errors().length == 0) {
//submit the form
}
else {
yourViewModel.Errors.showAllMessages();
//this line shows all the errors if validation fails,
//but you can omit this.
}

MVC 3 Client side validation on jQuery dialog

I am showing lots of form using jquery dialog and I wish to add in client side validation on it. I read through some examples, saying that mvc 3 already somehow support jquery client side validation, but I tried by including the necessary script, and my form like this:
#using (Html.BeginForm("CreateFood", "Home", FormMethod.Post, new { id = "formData" }))
{
#Html.ValidationSummary(false, "Please fix these errors.")
When i try to submit my form without fill in the required field, I still dint get any message. Can anyone give me more idea / explanation / examples on this??
Really needs help here... Thanks...
UPDATE (add in the script for my dialog)
$createdialog.dialog("option", "buttons", {
"Cancel": function () {
//alert('Cancel');
$createdialog.dialog('close');
},
"Submit": function () {
var frm = $('#formData');
$.ajax({
url: '/Food/CreateFood',
type: 'POST',
data: frm.serialize(),
success: $createdialog.dialog('close')
});
}
});
Once dropped, open dialog:
// Once drop, open dialog to create food
options.drop = function (event, ui) {
// Get the ContainerImgName which food dropped at
var cimg = $(this).attr('id');
// Pass in ContainerImgName to retrieve respective ContainerID
// Once success, set the container hidden field value in the FoodForm
$.ajax({
url: '/food/getcontainerid',
type: 'GET',
data: { cImg: cimg },
success: function (result) { $('#containerID').val(result); }
});
clear();
$.validator.unobtrusive.parse($createdialog);
$createdialog.dialog('open');
};
I've faced the same problem, solved with:
$(name).dialog({
autoOpen: true,
width: options.witdth,
heigth: options.height,
resizable: true,
draggable: true,
title: options.title,
modal: true,
open: function (event, ui) {
// Enable validation for unobtrusive stuffs
$(this).load(options.url, function () {
var $jQval = $.validator;
$jQval.unobtrusive.parse($(this));
});
}
});
of course you can add the validation on the close event of the dialog, depends on what you're doing, in my case the popup was just for displaying errors so I've performed validation on load of the content. (this pop up is displaying am Action result)
For every dynamically generated form you need to manually run the validator once you inject this content into the DOM as shown in this blog post using the $.validator.unobtrusive.parse function.

Using jqGrid's inline-editing with RESTful urls?

I'm using jqGrid and would like to be able to use its built-in editing functions to make ajax calls to add/edit/delete. Our API uses RESTful verbs and urls like so:
verb url action
--------------------------------------------------------------
GET /api/widgets get all widgets (to populate grid)
POST /api/widgets create new widget
PUT /api/widgets/1 update widget 1
DELETE /api/widgets/1 delete widget 1
Is it possible to use the built-in ajax handling with these restrictions, or do I have to use local data (as outlined here & here) and manage the ajax calls myself? If it is possible, what properties do I set on the grid?
(ajaxRowOptions looks promising, but the documentation is a bit thin on how to use it.)
The usage of POST in Add form is by default.
The main idea for customizing jqGrid for RESTfull backend you can find in the old answer.
To use 'DELETE' in form editing if you use the Delete button of the navigator toolbar. Look at here or here. So you should use about the following settings:
$("#grid").jqGrid('navGrid', '#pager',
{edit: false, add: false, search: false}, {}, {},
{ // Delete parameters
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url = '/api/widgets/' + encodeURIComponent(postdata);
}
});
I use in the example above the encodeURIComponent function to be sure that if the id will have some special characters (spaces for example) if will be encoded so that the server part automatically received the original (decoded) data. Probably you will need to set some additional settings for the $.ajax call used during sending Delete request to the server. You can use for it ajaxDelOptions property.
You can make the above settings as your default settings. You can do this with respect of the following
$.extend($.jgrid.del, {
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url = '/api/widgets/' + encodeURIComponent(postdata);
}
});
The method onclickSubmit from the example above can be used for the Edit operations (in case of form editing) to modify the URL dynamically to /api/widgets/1. In many cases the usage of onclickSubmit in the above form is not possible because one need to use different base urls ('/api/widgets') different grids. In the case one can use
$.extend($.jgrid.del, {
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata);
}
});
Then the usage of navGrid should be with explicit setting of url
$("#grid").jqGrid('navGrid', '#pager',
{edit: false, add: false, search: false}, {}, {},
{ // Delete parameters
url: '/api/widgets'
});
and
To use 'PUT' in inline editing you can set the following default jqGrid settings:
$.extend($.jgrid.defaults, {
ajaxRowOptions: { contentType: "application/json", type: "PUT", async: true },
serializeRowData: function (data) {
var propertyName, propertyValue, dataToSend = {};
for (propertyName in data) {
if (data.hasOwnProperty(propertyName)) {
propertyValue = data[propertyName];
if ($.isFunction(propertyValue)) {
dataToSend[propertyName] = propertyValue();
} else {
dataToSend[propertyName] = propertyValue;
}
}
}
return JSON.stringify(dataToSend);
}
});
The setting contentType: "application/json" is not required in general, but it could be required for some server technologies. The callback function serializeRowData from the example above sent the data as JSON. It is not required for RESTfull, but it's very common. The function JSON.stringify is native implemented in the most recent web browsers, but to be sure that it work in old browsers to you should include json2.js on your page.
The code of serializeRowData could be very simple like
serializeRowData: function (data) {
return JSON.stringify(data);
}
but I use above code to be able to use functions inside of the extraparam of the method editRow (see here and the problem description here).
The usage of the RESTfull URL (like /api/widgets/1) in the editRow is very simple:
$(this).editRow(rowid, true, null, null, '/api/widgets/' + encodeURIComponent(rowid));
To use it in case of the form editing you should use
grid.navGrid('#pager', {},
{ mtype: "PUT", url: '/api/widgets' });
and
$.extend($.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" }, // can be not required
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata.list_id);
}
});
It is important to remark that to get id from the postdata inside of onclickSubmit and need use postdata.list_id instead of postdata.id, where 'list' is the id of the grid. To be able to use different grid (<table>) ids one can use new non-standard parameter. For example, in the code below I use myGridId:
var myEditUrlBase = '/api/widgets';
grid.navGrid('#pager', {},
{ mtype: "PUT", url: myEditUrlBase, myGridId: 'list' },
{ // Add options
url: myEditUrlBase },
{ // Delete options
url: myEditUrlBase });
and the default setting defined as
$.extend($.jgrid.del, {
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata);
}
});
$.extend($.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" }, // can be not required
onclickSubmit: function (params, postdata) {
params.url += '/' + encodeURIComponent(postdata[params.myGridId + '_id']);
}
});
In case of the usage of formatter:'actions' (see here and here) with inline or form editing (or a mix) you can use the same technique as described before, but forward all needed Edit/Delete option using editOptions and delOptions formatoptions.
The last your question was the usage of GET as /api/widgets. The classical RESTfull services will returns just array of all items as the response on /api/widgets. So you should just use loadonce: true and jsonReader which used methods instead of properties (See here and here).
loadonce: true,
jsonReader: {
repeatitems: false,
root: function (obj) { return obj; },
page: function () { return 1; },
total: function () { return 1; },
records: function (obj) { return obj.length; }
}
You should in some way include information which item property can be used as the id of grid rows. The id must be unique on the page. It your data has no id I would recommend you to use
id: function () { return $.jgrid.randId(); }
as an additional jsonReader method because per default the current version of jqGrid use sequential integers ("1", "2", "3", ...) as the row ids. In case of having at least two grids on the same page it will follow to the problems.
If the size of the data returned by 'GET' are more as 100 rows I would you recommend better to use server side paging. It means that you will add an additional method in the server part which support server side sorting and paging of data. I recommend you to read the answer where I described why the standard format of the input data are not RESTfull array of items and has page, total and records additionally. The new method will be probably not strange for the classical RESTful design, but the sorting and paging data in native or even SQL code can improve the total performance from the side of enduser dramatically. If the names of the standard jqGrid input parameters (page, rows, sidx and sord) you can use prmNames jqGrid parameter to rename there.
Also check out this excellent general tutorial for how to set-up jqGrid for RESTful URL's here, which also includes how the corresponding Spring MVC server portion would look.
I have managed to achieve it by implementing beforeSubmitCell event handler:
beforeSubmitCell: function(rowId) {
jQuery("#grid-HumanResource-table").jqGrid(
'setGridParam',
{
cellurl: s.getBaseModule().config.baseAPIUrl + "humanResource/" + rowId
}
);
},
I am using jqGrid 4.6 version.

How to pass extra parameter to Add and Edit url in jqGrid

Order id is stored in variable _documentId and changed in runtime by ajax call if new order is saved to actual it.
If adding new detail row to jqGrid Add form url or inline Edit url reqires this id also.
I tried to use postdata but _documentId is not passed if Edit and Add urls are called.
How to pass _documentId value to those urls ?
var _documentId; // assigned from ajax call after save.
$(function () {
var grid = $("#grid");
grid.jqGrid({
postData: {_documentId: function() { return _documentId } },
editurl: 'Edit', // How to pass _documentId value to this controller ?
url: 'GetData',
datatype: "json",
mtype: 'POST',
scroll: 1,
multiselect: true,
multiboxonly: true,
scrollingRows : true,
autoencode: true,
prmNames: {id:"_rowid", oper: "_oper" },
colModel: <%= Model.ColModel() %>,
gridview: true,
toppager: true,
viewrecords: true
});
grid.navGrid("#grid_toppager", {}, {}
{ url: 'Add' } // How to pass _documentId value to this controller ?
);
In case of form editing, you should use editData parameter to send additional data to the server. Another way is to modify the postdata inside of onclickSubmit or beforeSubmit event handler. You can of course do it in the serializeEditData event handler instead. Using onclickSubmit, you can easy modify the URL (params.url) if you need really place the information in the URL and not in the data which will be send to the server.
In case of inline editing, you can use extraparam parameter of the editRow or use serializeRowData event handler.

Handling objects and routes with MVC3/Razor?

I have a geo collection that contains items like:
[state name]
[city], [state]
[country]
A text box is available for a user to begin typing, and a jQuery autocomplete box fills displays possible options.
The URL structure of the post request will depend on which was selected from the collection above, ie
www.mysite.com/allstates/someterms (if a country is selected)
www.mysite.com/city-state/someterms (if a city, state is selected)
www.mysite.com/[state name]/someterms (if a state is selected)
These are already defined in my routes.
I was initially going to add some logic on the controller to determine the appropriate URL structure, but I was thinking to simply add that as an additional field in the geo table, so it would be a property of the geo collection.
Here is my jQuery function to display the collection details when, fired on keypress in the textbox:
$(function () {
$("#txtGeoLocation").autocomplete(txtGeoLocation, {
source: function (request, response) {
$.ajax({
url: "/home/FindLocations", type: "POST",
dataType: "json",
selectFirst: true,
autoFill: true,
mustMatch: true,
data: { searchText: request.term, maxResults: 10 },
success: function (data) {
response($.map(data, function (item) {
return { label: item.GeoDisplay, value: item.GeoDisplay, id: item.GeoID }
}))
}
})
},
select: function (event, ui) {
alert(ui.item ? ("You picked '" + ui.item.label + "' with an ID of " + ui.item.id)
: "Nothing selected, input was " + this.value);
document.getElementById("hidLocation").value = ui.item.id;
}
});
});
What I would like is to have structure the URL based on an object parameter (seems the simplest). I can only seem to read the parameters on "selected", and not on button click.
How can I accomplish this?
Thanks.
To resolve this, I removed the select: portion from the Javascript, and added the selected object parameters in the MVC route sent to my controller.

Resources