I have a datagrid where I need to validate the input based on another field in the table. I haven't found a clean way to do this yet. This is a simple shopping cart type use case. I'm sure there is a better way but I needed to get this out quickly.
I have setup a datagrid that lists the items that the user has selected. They can change the quantity using a numericedit control. Different items(products) have different increment values (i.e. 1 or 25). I would like to do a client side validation to make sure the value meets the increment requirements. For example:
return ( item.Quantity % item.Increment == 0)
Looking at the client side validation I can only get the value in the control and I don't have dynamic access to the other fields in the row. Hopefully I missed something.
Another thing I would like to do is to set the STEP property of the numericedit based on the increment in other words row by row. I haven't found a way to do this either.
I can check the values on the server and return an error. However, I need to check more than one value in my case the order total cannot exceed a limit. Therefore I want to return a custom error message so the user knows which rule was violated.
I found this post: https://www.syncfusion.com/forums/185397/actionfailure-missing-args which shows how to pass a custom error message back. However, throwing exceptions is problematic on my hosting provider. It works in my test environment but not in production.
I was hoping I could accomplish the same thing by passing back a BadRequest("error message") back. This works well when doing an AJAX call but not in the actionFailure event.
I appreciate any feedback on this issue.
Hi
Chris Franz,
Greetings from Syncfusion support.
Query#1: Looking at the client side validation I can only get the
value in the control and I don't have dynamic access to the other fields in the
row. Hopefully I missed something.
You can access the other field's value within the validation function by
selecting the input from the parent row. Refer to the code example below for
more details.
|
function customFn(args) { var parentRow = args.element.closest('tr'); var FreightValue = parentRow.querySelector('#GridFreight').ej2_instances[0].value; // here “Grid” is the Grid component id value; return args['value'].length >= 5; };
|
In the screenshot below, the custom validation function is triggered for the CustomerID field, and within it, the Freight field value is accessed.
|
|
Query#2: I would like to do is to set the STEP property of the numericedit based on the increment in other words row by row. I haven't found a way to do this either.
You can dynamically customize the edit control within the "actionComplete" event. Refer to the code example below, where the step is modified only if the Role value of that row is "Admin".
|
function actionComplete(args) { if (args.requestType == 'beginEdit' && args.rowData.Role == 'Admin') { args.row.querySelector('.e-numerictextbox').ej2_instances[0].step = 2; } }
|
https://ej2.syncfusion.com/javascript/documentation/api/grid/#actioncomplete
Query#3: I can check the values on the server and return an error.
However, I need to check more than one value in my case the order total cannot
exceed a limit. Therefore I want to return a custom error message so the user
knows which rule was violated.
You can perform the server-side validation by using the “actionBegin”
event of the Grid component. Inside the event handler with “save”
requestType, you can prevent the default save action by setting the “args.cancel”
property as true and perform the server-side validation. Based on the
validation result, you can save the values or hold the Grid on edit state.
Please refer to the below code example and KB link for more information.
|
var doValidation = true; function actionBegin(e) { var grid = document.getElementById("InlineEditing").ej2_instances[0]; if (e.requestType === 'save') { if (doValidation) { // Flag to allow validation, initial value is true e.cancel = true; // Cancel the default "save" action // Perform the server validation var ajax = new ej.base.Ajax({ url: "/Home/Data", type: "POST", contentType: 'application/json; charset=utf-8', data: JSON.stringify({ value: e.data["CustomerID"] }), successHandler: function (data) { // Display the message when value has duplicate if (JSON.parse(data).result) { alert("Entered value contains Duplicate CustomerID"); } else { doValidation = false; grid.endEdit(); } } }); ajax.send();
} else { doValidation = true; } } }
|
https://support.syncfusion.com/kb/article/11608/how-to-do-server-side-validation-for-grid-in-asp-net-mvc-application
Please get back to us if you need further assistance.
Regards,
Pavithra S
I tried the code samples that you sent and I did not get the results I need. When my custom function runs here is the content I get.
args = {"element":{"__eventList":{"events":[{"name":"focusout"},{"name":"keyup"}]}},"value":"22"}
I am not getting any information about the element as referenced in your example above. Here is the code that I am using for the load event and my custom function
function load(args) {
var grid = document.getElementById("dgOrderDetail").ej2_instances[0];
grid.getColumnByField("ItemQuantity").validationRules = { required: true, minLength: [customFunction, 'Invalid quantity'] };
}
function customFunction(args) {
var parentRow = args.element.closest('tr');
var rowValue = parentRow.querySelector('#dgOrderDetail').ej2_instances[0].value;
return args['value'] % rowValue.Increment == 0;
};
What am I missing?
Also, when working on changing the step value I am not in admin mode so the code doesn't work. It is important to note here that the actionComplete does not fire until a save. It does not fire on a beginEdit. Moving the code to the beginEdit event fires before editing but the step value is never changed.
The args contains the rowData but I don't see the role property of the rowData.
function onBeginEdit(args){
alert(JSON.stringify(args));
if (args.requestType == 'beginEdit') {
alert('Change the increment')
args.row.querySelector('.e-numerictextbox').ej2_instances[0].step = args.rowData.Increment;
}
}Hopefully, I am just missing something simple.
Chris,
Query#1: I am not getting any information about the element as
referenced in your example above. Here is the code that I am using for the load
event and my custom function
By default, the custom validation function receives the element currently being validated. Please see the screenshot below.
|
|
However, you can also retrieve the value of another field by accessing the grid edit form element, as shown in the example below.
|
function customFunction(args) {
var grid = document.getElementById('dgOrderDetail').ej2_instances[0];
// here “Freight” is the field name. you can replace this field name here. var value = grid.editModule.formObj.element.querySelector( '#' + grid.element.id + 'Freight').ej2_instances[0].value; return args['value'] % value == 0; // change the code here as per your requirement. }
|
Query#2: Moving
the code to the beginEdit event fires before editing but the step value is
never changed.
You
can achieve the same inside the beginEdit event by using the below code
example.
|
function beginEdit(args) { if (args.requestType === 'beginEdit') { let column = grid.getColumnByField('Freight'); // here replace your field name with “Freight” column.edit.params = { step: args.rowData.Increment}; } }
|
https://ej2.syncfusion.com/javascript/documentation/api/grid#getcolumnbyfield
Thanks for the information. I was able to get the step increment set based on the selected row.
Unfortunately, I sill cannot get the validation rule to work properly. I keep getting a null error on the line: var value = grid.editModule.formObj.element.querySelector( '#' + grid.element.id + 'Increment').ej2_instances[0].value;
Here is the error message:
Uncaught TypeError: Cannot read properties of null (reading 'ej2_instances')
at KO.customFunction (LugBulk:356:104)
at KO.isValid (ej2.min.js:10:1874282)
at KO.validateRules (ej2.min.js:10:1872006)
at KO.validate (ej2.min.js:10:1865536)
at KO.focusOutHandler (ej2.min.js:10:1870673)
at PL.focusOutHandler (ej2.min.js:10:1752810)
The documentation does not have much information on the editModule. I have not found any details on the formObj or the querySelector.
Here is my updated code based on your suggestions:
function load(args) {
var grid = document.getElementById("dgOrderDetail").ej2_instances[0];
grid.getColumnByField("ItemQuantity").validationRules = { required: true, minLength: [customFunction, 'Invalid quantity'] };
}
// Validate the increment value for the current row
function customFunction(args) {
var grid = document.getElementById('dgOrderDetail').ej2_instances[0];
var value = grid.editModule.formObj.element.querySelector( '#' + grid.element.id + 'Increment').ej2_instances[0].value; // getting a null error on this line
return (args['value'] % value) == 0;
}Still making progress just this last issue.
Hi Chris Franz,
We suspect that the issue might be due to one of the following reasons:
To resolve this, you can access the rowData value through the actionBegin event's arguments instead of querying the DOM. This approach ensures that the value is available even if the column is not visible or does not have an input field in the form.
Suggested Solution:
Instead of using querySelector, retrieve the Increment field value using grid.editModule.editModule.args.rowData.Increment or properly define the template input control name attribute as grid.element.id + respective field name.
This approach ensures that the validation logic works even for non-visible columns.
Please refer to the JavaScript (ES5) reference sample for further details:
JavaScript (ES5) Reference Sample: https://stackblitz.com/edit/khmobtkk?file=index.js,index.html
Template editing form: https://ej2.syncfusion.com/aspnetcore/documentation/grid/editing/template-editing?cs-save-lang=1&cs-lang=csharp#inline-or-dialog-template-editing
[code example]
|
// Validate the increment value for the current row function customFunction(args) { var grid = document.getElementById('dgOrderDetail').ej2_instances[0]; var value = grid.editModule.editModule.args.rowData.Increment; // not defined/visible other column-based validation purpose, we can access actionBegin rowData argument from grid editModule. return (args['value'] % value) == 0; } |
Next Steps:
If the issue persists, please provide the following details for further investigation:
Providing these details will help us validate and offer a more precise solution for your custom validation requirement.
Regards,
Vasanthakumar K
Vasanthakumar,
The increment field is a hidden field. When I made it visible the code from above worked perfectly.
Since I show the increment in a template the new solution you proposed was a better choice for me.
Thank you for the solution!
Chris
Chris,
Thanks for your update. We are happy to hear that your issue has been resolved.
Please get back to us if you need further assistance on this.