how to render and input column cell with different types

Hi all,
I have the following use case:
a grid included in an asp.net core view which retrieves data source through a data manager with url adaptor

        <ejs-grid id="..." ...>
            <e-data-manager url="@Url.Action("...", "...")" batchUrl="@Url.Action("...", "...")" adaptor="UrlAdaptor" />
            <e-grid-columns>
               ...
            </e-grid-columns>
        </ejs-grid>

the columns are declared statically, however two of them include the main data value (a string) and the value type
actually, value type can be 'number', 'bool', 'text', and based on this type I need the cell contains different control (spinbox, textbox, checkbox respectively) to show the data value. No problem the convertion, I could do on my side, but what I need is the value being represented with different control both when retrieving and when saving, which I execute in batch mode (see data-manager)
I've considered using templates but as far as I understood they anyway apply to the whole column, while I need different cells type on the same column.
Is this possible with Grid? if so how?
Alternatively, if another control is more suitable, I'd consider as well...
please help.
Thank you


14 Replies

TS Thiyagu Subramani Syncfusion Team March 20, 2020 11:38 AM UTC

Hi Silvia, 

Thanks for contacting Syncfusion. 

Query : I need different cells type on the same column. Is this possible with Grid? 
 
Yes, we can possible to implement different cells type on the same column. Here we have achieved textbox and checkbox in ShipCity column based on the value. 

So, using this way we can achieve your requirement. Please refer to the below code and sample. 

<ejs-grid id="DefaultGrid" allowPaging="true"  toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })"> 
    <e-data-manager url="/home/UrlDatasource" batchUrl="/Home/BatchUpdate" adaptor="UrlAdaptor"></e-data-manager> 
    <e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Batch"></e-grid-editSettings> 
    <e-grid-columns> 
        . . . . . . 
        <e-grid-column field="ShipCity" headerText="ShipCity" width="120" edit="@(new {create="fileCreate", read="fileRead", destroy="fileDestroy", write="fileWrite"  })"></e-grid-column> 
    </e-grid-columns> 
</ejs-grid> 
 
<script type="text/javascript"> 
    var elem; 
    var elementObj; 
    var checked; 
    function fileCreate() { 
        elem = document.createElement('input'); 
        return elem; 
    } 
    function fileRead(args) { 
        debugger; 
        if (elementObj.element.classList.contains('e-checkbox')) { 
            return elementObj.checked; 
        } 
        else { 
            return elementObj.value; 
        } 
    } 
    function fileDestroy() { 
        elementObj.destroy(); 
    } 
    function fileWrite(args) { 
        if (args.rowData.ShipCity === "false" || args.rowData.ShipCity === "true") { 
            if (args.rowData.ShipCity === "false") checked = false; if (args.rowData.ShipCity === "true") checked = true; 
            elementObj = new ej.buttons.CheckBox({  
                checked: checked 
            }); 
            elementObj.appendTo(elem); 
        } 
        else { 
            elementObj = new ej.inputs.TextBox({ 
                value: args.rowData.ShipCity 
            }); 
            elementObj.appendTo(elem); 
        } 
    } 
</script> 



Please get back to us, if you need any further assistance. 

Regards, 
Thiyagu S. 



SG Silvia Giunciuglio March 29, 2020 11:56 PM UTC

Hi all,
thank you for your support, I managed the grid for editing different controls for different field types.
Then I added some logic to represent the values initially, when the grid is not yet in editing mode, using column templates and conditional expressions
Now I'm trying to add validation, still for editing mode, I continued on the same approach you suggested creating a form validator together with the control for the field, but when validate() is invoked, following error is thrown:



here are the implementation of the four editing events: create, write, read, destroy
then the cellSave event handler (which is invoked after read) where the validation is performed:

    static onEditFieldCreateValue()
    {
        $("#divLog").append("<div>onCreateFieldValue </div>");

        this._gridFieldValueInputElement = document.createElement("input");
        return this._gridFieldValueInputElement;
    }

    static onEditFieldWriteValue(args)
    {
        $("#divLog").append("<div>onWriteFieldValue </div>");

        var inputControl = null;
        var integerValidatorIsRequired = false;
        var textValidatorIsRequired = false;

        switch (args.rowData.FieldType)
        {
            case "integer":
                inputControl = new ej.inputs.NumericTextBox({
                    value: parseInt(args.rowData[args.column.field]),
                    format: "n0",
                    decimals: 0,
                    validateDecimalOnType: true,
                    locale: this.getGrid().locale,
                });
                var range = this.getRangeForFieldValue(args.rowData["Range"]);
                if (range != null)
                {
                    inputControl.min = (<any>range).min;
                    inputControl.max = (<any>range).max;
                    inputControl.strictMode = true;
                }
                integerValidatorIsRequired = true;
                break;

            case "text":
                inputControl = new ej.inputs.TextBox({
                    value: args.rowData[args.column.field],
                    locale: this.getGrid().locale,
                });
                textValidatorIsRequired = true;
                break;

            case "boolean":
                inputControl = new ej.buttons.CheckBox({
                    checked: args.rowData[args.column.field] == "true",
                    locale: this.getGrid().locale,
                });
                break;
        }

        if (inputControl != null)
        {
            this._gridFieldValueInputCtrl = inputControl;
            this._gridFieldValueInputCtrl.appendTo(this._gridFieldValueInputElement);

            if (integerValidatorIsRequired)
            {
                this._gridFieldValueInputValidator = new ej.inputs.FormValidator("#gridCfgGlobEditForm", {
                    rules: { "gridCfgGlobFieldValue": { required: true } }
                });
            }
            else if (textValidatorIsRequired)
            {
                var validationOptions;
                if (args.rowData.Regex != null)
                {
                    validationOptions = {
                        rules: {
                            "gridCfgGlobFieldValue": {
                                required: true,
                                regex: args.rowData.Regex
                            }
                        }
                    }
                }
                else
                {
                    validationOptions = {
                        rules: { "gridCfgGlobFieldValue": { required: true } }
                    }
                }

                this._gridFieldValueInputValidator = new ej.inputs.FormValidator("#gridCfgGlobEditForm", validationOptions);
            }
        }
    }

    static onEditFieldReadValue()
    {
        $("#divLog").append("<div>onReadFieldValue </div>");

        //if (this._gridFieldValueInputCtrl.element.classList.contains("e-checkbox"))
        if (this._gridFieldValueInputCtrl.checked != undefined)
            return this._gridFieldValueInputCtrl.checked ? "true" : "false";
        else if (this._gridFieldValueInputCtrl.step != undefined)
            return this._gridFieldValueInputCtrl.value.toString();
        else
            return this._gridFieldValueInputCtrl.value;
    }

    static onEditFieldDestroyValue()
    {
        $("#divLog").append("<div>onDestroyFieldValue =====================</div>");

        this._gridFieldValueInputCtrl.destroy();
        this._gridFieldValueInputCtrl = null;

        if (this._gridFieldValueInputValidator != null)
        {
            this._gridFieldValueInputValidator.destroy();
            this._gridFieldValueInputValidator = null;
        }
    }

    ...

    static onCellSave(args: CellSaveArgs)
    {
        $("#divLog").append("<div>onCellSave colIdx:" + args.columnObject.index + "</div>");
        var cellIsValid = true;
        if (ConfigGlobal._gridFieldValueInputValidator != null)
            cellIsValid = ConfigGlobal._gridFieldValueInputValidator.validate();

        if (!cellIsValid)
            args.cancel = true;
        else
        {
            if ((<any>args.rowData).FieldType == "integer")
                args.value = parseInt(args.value).toString();
            ComponentBase.addChange((<any>args.rowData).Id, args.columnName, args.previousValue, args.value);
        }
    }

Is my approach correct? I did not add validation rules on the entire column because again, data can be of different types and the fields can have different validators based on type and even others row data fields (regex for text fields)
Please let me know
Thank you


TS Thiyagu Subramani Syncfusion Team March 30, 2020 02:38 PM UTC

Hi Silvia, 

Thanks for your update. 

Query : Need to set different validators for different types. 
 
We can achieve this requirement by setting different validation messages for different data type inputs and set validation message as empty in while saving the modified value using cellSave method. Please refer to the below code and sample link. 

In this sample we have defined required true validation message in textbox and in save method we defined validation message as empty. 

<script type="text/javascript"> 
    var elem; 
    var elementObj; 
    var checked; 
    var gridObj; 
    function fileCreate() { 
        elem = document.createElement('input'); 
        return elem; 
    } 
    document.addEventListener('DOMContentLoaded', function () { 
        gridObj = document.getElementsByClassName('e-grid')[0].ej2_instances[0]; 
    }); 
 
    function save(args) { 
        gridObj.columns[2].validationRules = ""; 
    } 
     
    function fileRead(args) { 
        debugger; 
            if (elementObj.element.classList.contains('e-checkbox')) { 
                return elementObj.checked; 
            } 
            else { 
                return elementObj.value; 
            } 
        } 
    function fileDestroy() { 
        elementObj.destroy(); 
    } 
    function fileWrite(args) { 
        if (args.rowData.ShipCity === "false" || args.rowData.ShipCity === "true") { 
            if (args.rowData.ShipCity === "false") checked = false; if (args.rowData.ShipCity === "true") checked = true; 
            elementObj = new ej.buttons.CheckBox({  
                checked: checked 
            }); 
            elementObj.appendTo(elem); 
            
        } 
        else {  
            elementObj = new ej.inputs.TextBox({ 
                value: args.rowData.ShipCity 
            }); 
            elementObj.appendTo(elem); 
            gridObj.columns[2].validationRules = { required: true }; // required column 
        } 
    } 
</script> 


If still facing this issue, please share the below details. 

  1. If we misunderstood your issue please explain briefly?
  2. Share your complete code.
  3. Video demonstration of you issue.
  4. Reproduce the issue in attached sample.

Please get back to us, if you need any further assistance. 

Regards, 
Thiyagu S 



SG Silvia Giunciuglio April 6, 2020 05:50 PM UTC

Hi all,
thank you for your support, and sorry for my not really well-timed feedback.
I'm not sure you addressed my problem, though; I think your suggestion would enable or disable the validation rule for all the cells of the columns but my case is different, let me give more details:

1.

I have a data table like this one:



each row represents a parameter, and each one can be of type number, text, boolean. The range applies only for numbers, while the regex only to texts, and they are both optionals. In the entity, the value is stored as a string no matter the type.

2.

in the web app that acts as HMI, I succeed to render the data in this manner, as I wished:



columns id, type, and regex are there but not visible to the user.
when the grid is in readonly mode (all columns have allowEditing=false) I render different input formats using templates.
when the grid is in editing mode (value column has allowEditing=true) I use your suggestion for batch mode cell editing lifecycle (create - write - read - destroy) and I also succeeded to create the right control on the fly just for edit the value (NumericTextBox, TextBox, CheckBox respectively) I posted my code previously.

3.

What I miss now is validation:
- numbers are required and should be in range, when specified
- texts are required and should comply with regex, when specified
- no validation for booleans

so far, I tried interacting with formValidator, which I noticed included into grid cell under editing when I just create the input control, but SyncFusion gives me the error I show you in the previous post.
How can I apply different validators for different cells in the same column, base on type which is another column of the data coming from web server? Taking into account also that validations require additional data fields base on type (range, regex, as said above).
Is my approach correct or there could be a better different one?
Please use these details with the code I posted earlier, I hope thing would become more clear

Thank you so much, please let me know your suggestions.



TS Thiyagu Subramani Syncfusion Team April 8, 2020 02:03 PM UTC

Hi Silvia, 

Thanks for your update. 

We have validated your requirement and addressed below queries. 

Query 1: When the grid is in readonly mode (all columns have allowEditing=false) I render different input formats using templates. 
 
If we set allowEditing as false in column, when editing the row required column will be on non-editable state. So, we can’t render any input formats using template. 

Query 2: Numbers are required and should be in range, when specified & texts are required and should comply with regex, when specified & no validation for booleans 
 
For this case, you can achieve your requirement using custom validation. We have already discussed in this topic in below documentation. Please refer it. 
 

Please get back to us, if you need any further assistance. 

Regards, 

Thiyagu S. 



SG Silvia Giunciuglio April 14, 2020 07:31 AM UTC

Hi all,

about query 1 actually it works because I managed my hmi appl in two modes: readonly and edit, and when the user is allowed, he can switch between the twos; readonly mode is obtained setting on browser side - through javascript - all columns not editable, while the edit mode is obtained simply setting value column as editable. As this was part of the initial question I gave update on this so you have a better view of the domain - I believed.

about query 2, this is where my doubts are now focused, before posting last request, I read documentation about custom validator, but I was not sure this approach could be used because I saw a custom validator almost declarative while I'd need one using a more complex function; that's why my approach was to use the form validator created automatically with editing control in the cell.
Which of the two approaches is more correct and more suitable for me?

To summarize, I need my validator could access row data (to get type of the value to validate and other data for range and regex checking and possibly the error message to show to the user, which could be also embedded into data row) and return the right value to notify syncfusion grid the cell is valid or not, with custom not hardcoded error notification message.

Thank you for your support.
Regards,
Silvia



TS Thiyagu Subramani Syncfusion Team April 17, 2020 02:45 PM UTC

Hi Silvia, 

Thanks for your update. 

Query 1 : All columns not editable, while the edit mode is obtained simply setting value column as editable. 

By default in allowEditing as false, when editing the row required column will be in non-editable state and so we didn’t consider validation for that column. For this case you can validate that required column by externally.  

Query 2 : Which of the two approaches is more correct and more suitable for me? 
 
You can use custom validator for validation based on your application. In custom validation function you can use any kind of regex or complex foe validate your required input. 

Please refer the below sample for custom validation message. 

For reference , 


 


Please get back to us, if you need any further assistance. 

Regards, 
Thiyagu S. 



SG Silvia Giunciuglio April 17, 2020 07:48 PM UTC

Hi Thiyagu Subramani,

Thank you for your answer
I already read in documentation about custom validation earlier, but i cannot figure out how given example can fit my requirements.

In the javascript function for custom validation 

var customFn = function(args) {
    return args['value'].length >= 5;
};

can you show me an implementation example where row data of the grid is accessed inside that custom validation function? What if the hardcoded maximum length of 5 is needed to be retrieved in the grid row data rather than being a constant?

also, as stated earlier, I need the error message being not hardcoded as well, so

var grid = new ej.grids.Grid({
    dataSource: data,
    toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
    editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' },
    columns: [
        { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 100, isPrimaryKey: true, validationRules: { required: true } },
        { field: 'CustomerID', headerText: 'Customer ID', width: 120, validationRules: { required: true, minLength: [customFn, 'Need atleast 5 letters'] } },
        { field: 'Freight', headerText: 'Freight', textAlign: 'Right', editType: 'numericedit', width: 120, format: 'C2' },
        { field: 'ShipCountry', headerText: 'Ship Country', editType: 'dropdownedit', width: 150 }
    ],
    height: 273
});

how can it be done the error message not being hardcoded and constant as 'Need at least 5 letters' but instead contained in the same data table of the grid?

thank you



MF Mohammed Farook J Syncfusion Team April 20, 2020 01:10 PM UTC

  
Hi Silvia, 
 
Thanks for update. 
 
We have validated the provide code example and please find the explanation from the following code 
 
var grid = new ej.grids.Grid({ 
    dataSource: data, 
    toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'], 
    editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' }, 
    columns: [ 
        { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 100, isPrimaryKey: true, validationRules: { required: true } }, 
        { field: 'CustomerID', headerText: 'Customer ID', width: 120, validationRules: { required: true, minLength: [customFn, 'Need atleast 5 letters'] } }, 
        { field: 'Freight', headerText: 'Freight', textAlign: 'Right', editType: 'numericedit', width: 120, format: 'C2' }, 
        { field: 'ShipCountry', headerText: 'Ship Country', editType: 'dropdownedit', width: 150 } 
    ], 
    height: 273 
}); 
 
In the above demo we have used minLength validation for the customerID column. By default minLength accept only integer value(above sample we have validated the text length as minimum as 5) .It validated the text and return true/false when the text length is exceed its minLength are not.  
 
var customFn = function(args) {    return args['value'].length >= 5;};
 
In the above custom function , we can directly validated the text length which is exceed 5 or not.  You can also performing custom Regex here. This is not meet your requirement could you please explain more details about your requirement. 
 
Regards, 
J Mohammed Farook  
 
 
 
 
 
 
 
 



MF Mohammed Farook J Syncfusion Team April 20, 2020 01:11 PM UTC

  
Hi Silvia, 
 
Thanks for update. 
 
We have validated the provide code example and please find the explanation from the following code 
 
var grid = new ej.grids.Grid({ 
    dataSource: data, 
    toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'], 
    editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' }, 
    columns: [ 
        { field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 100, isPrimaryKey: true, validationRules: { required: true } }, 
        { field: 'CustomerID', headerText: 'Customer ID', width: 120, validationRules: { required: true, minLength: [customFn, 'Need atleast 5 letters'] } }, 
        { field: 'Freight', headerText: 'Freight', textAlign: 'Right', editType: 'numericedit', width: 120, format: 'C2' }, 
        { field: 'ShipCountry', headerText: 'Ship Country', editType: 'dropdownedit', width: 150 } 
    ], 
    height: 273 
}); 
 
In the above demo we have used minLength validation for the customerID column. By default minLength accept only integer value(above sample we have validated the text length as minimum as 5) .It validated the text and return true/false when the text length is exceed its minLength are not.  
 
var customFn = function(args) {    return args['value'].length >= 5;};
 
In the above custom function , we can directly validated the text length which is exceed 5 or not.  You can also performing custom Regex here. This is not meet your requirement could you please explain more details about your requirement. 
 
Regards, 
J Mohammed Farook  
 
 
 
 
 
 
 
 



SG Silvia Giunciuglio April 21, 2020 01:35 PM UTC

I already explained in previous posts, anyway if you need I'll try to explain again.

on server side, I have a datatable of entities like this one:

    public class CfgEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string FieldType { get; set; }
        public string FieldValue { get; set; }
        public string Range { get; set; }
        public string Regex { get; set; }
        public string ErrMsg { get; set; }
    }


I render it on web appl using a syncfusion grid in asp net core razor page:

  <ejs-grid id="myGrid" ...>
    <e-grid-editsettings mode="Batch" allowAdding="false" allowDeleting="false" allowEditing="true"
      showConfirmDialog="true" />
    <e-data-manager adaptor="UrlAdaptor" url="@Url.Action("GetCfgData", "Config")"
      batchUrl="@Url.Action("ExecCfgBatch", "Config")" />
    ...

    <e-grid-columns>
      <e-grid-column field="Id" visible="false" allowEditing="false" isPrimaryKey="true" />
      <e-grid-column field="Name" allowEditing="false" />
      <e-grid-column field="FieldType" visible="false" allowEditing="false" />
      <e-grid-column field="FieldValue" />
      <e-grid-column field="Range" textAlign="Right" allowEditing="false" />
    </e-grid-columns>
  </ejs-grid>

As you can notice, datasource is not specified because data is retrieved and saved through a dataManager with an url adaptor; editing is in batch mode.
Columns are id (primary key, not visible), Name, FieldType (not visible), FieldValue, Range; Regex and ErrMsg columns coming from server are not in the columns list of grid, but I saw in grid property dataRow also their data is accessible in javascript browser side. Only FieldValue is editable.

HMI screenshot is this one, I succeed to render and edit fieldValues with different controls based on FieldType column value.



this is where I am at this point.

Now I need a javascript validator on browser side that uses data fields in data rows to perform validation for a given cell of FieldValue column cell

validator should use value in FieldType for that row, it could be
  - "integer": check that value is specified (required) and in range specified by Range column for that row
  - "text": check that value matches regex specified by Regex column for that row
  - in case of input error, the error message shown to user should be the one contained in ErrMsg column for that row

Have you or your team ever seen use cases like this one? Is it possible to implement?
Regards,
Silvia




TS Thiyagu Subramani Syncfusion Team April 22, 2020 12:32 PM UTC

Hi Silvia, 
 
Thanks for your update. 
 
We have validated the requirement and you can achieved your requirement by using following way. 
 
 
<ejs-grid id="myGrid" ...> 
    <e-grid-editsettings mode="Batch" allowAdding="false" cellEdit ="cellEdit" allowDeleting="false" allowEditing="true" 
      showConfirmDialog="true" /> 
    <e-data-manager adaptor="UrlAdaptor" url="@Url.Action("GetCfgData", "Config")" 
    ... 
 
    <e-grid-columns> 
      <e-grid-column field="Id" visible="false" allowEditing="false" isPrimaryKey="true" /> 
      <e-grid-column field="Name" allowEditing="false" /> 
      <e-grid-column field="FieldType" visible="false" allowEditing="false" /> 
      <e-grid-column field="FieldValue" /> 
      <e-grid-column field="Range" textAlign="Right" allowEditing="false" /> 
    </e-grid-columns> 
  </ejs-grid> 
 
<script> 
var customFn1 = function(args) { 
    //  you can perform your own regx here 
}; 
var customFn2 = function(args) { 
 
      
}; 
var customFn3 = function(args) { 
//  you can perform your own regx here }; 
 
function cellEdit(e) { 
 
  if (e.columnName == 'FieldValue') { 
    //  check the column value is number set range validation 
    if (!isNaN(parseInt(e.rowData['FieldValue']))) { 
      this.getColumnByField('FieldValue').validationRules = { required: true, minLength: [customFn1, 'enter the value 1 to  10'] } 
    } 
//  check the column value as Boolean , no validation  
 
    if (e.rowData['customerID'] == 'true' || e.rowData['customerID'] == 'false') { 
      this.getColumnByField('FieldValue').validationRules = {} 
    } 
   //  check the column value is string set range minLength validation 
 
    else { 
      this.getColumnByField('FieldValue').validationRules = { required: true, minLength: [customFn2, 'Need atleast 3 letters'] } 
    } 
 
  } 
} 
</script> 
 
In the above code example we have applied different validation based on its value in same column (ie. ‘FieldValue’ column) by using ‘cellEdit’ event of Grid. In the ‘cellEdit’ event we have set the different validation through validationRules property of columns. 
 
Please get back to us, if you need any further assistance. 
 
Regards, 
Thiyagu S 



SG Silvia Giunciuglio April 30, 2020 03:45 PM UTC

hi team,
so the trick was to define validation rules, custom or standard, on the fly in cellEdit event.
I finally implemented my requirement, thank you for your hints.
Regards,
Silvia


RS Rajapandiyan Settu Syncfusion Team May 1, 2020 09:32 AM UTC

Hi Silvia, 

We are glad that the provided solution is resolved your requirement. Please get back to us if you need further assistance on this. 

Regards, 
Rajapandiyan S 


Loader.
Up arrow icon