How can I include a form in a dialog

Dear support,


In order to create new items, I would Like to include a form in a dialog.

When I click on the submit button of the form, I would like the dialog to be closed, and the form to get submitted.

How can I do ?

best regards




12 Replies

VJ Vinitha Jeyakumar Syncfusion Team July 5, 2021 12:58 PM UTC

Hi Sandra, 
 
 
Greetings from Syncfusion support.  
 
We have validated your query, “How can I include a form in a dialog. When I click on the submit button of the form, I would like the dialog to be closed, and the form to get submitted. 
 
Your requirement to include the form into the dialog and also to hide the dialog when clicking the form submit button can be achieved by using the button onclick event, in which you can use the “hide” public method of the dialog. We have prepared a sample for your reference,  
 
Code snippet: 
 
<template> 
    <div> 
        <div id="target" 
             class="control-section; position:relative" 
             style="height: 600px"> 
            <!-- Render Button to open the Dialog --> 
            <ejs-button id="modalBtn" v-on:click.native="btnClick">Open Dialog</ejs-button> 
            <!-- Render Dialog --> 
            <ejs-dialog id="dialog" 
                        ref="templateDialog" 
                        :target="target" 
                        :height="height" 
                        :width="width" 
                        :visible="false" 
                        :allowDragging="true" 
                        header="Dialog Form" 
                        :showCloseIcon="true"> 
                <div class="container"> 
                    <form> 
                        <div class="row"> 
                            <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> 
                            </div> 
                        </div> 
                        <div class="form-group"> 
                            <label>Input: </label> 
                            <input /> 
                        </div> 
                        <br /> 
                        <ejs-button id="modalBtn1" v-on:click.native="submitBtnClick">Submit</ejs-button> 
                    </form> 
                </div> 
            </ejs-dialog> 
        </div> 
    </div> 
</template> 
<script> 
. . . 
. . . 
export default { 
  . . . 
 . . .  
  methods: { 
    btnClick: function () { 
      this.$refs.templateDialog.show(); 
    }, 
    submitBtnClick: function () { 
      //dialog is closed by calling hide method. 
      this.$refs.templateDialog.hide(); 
      // submit button action functionalities can be written here. 
    }, 
  }, 
}; 
</script> 
 
 
Please check the above code snippet and the sample and let us know if it satisfies your requirement.  
  
Regards,  
Vinitha 



SB Sandra Bordier July 5, 2021 10:08 PM UTC

Dear support, 

Thank you for the answer, but is not exactly what I want. 

I can already close the dialog.
My main problem is that when I click on the submit button, is does not submit the form.

In fact, here is the whole thing : 

=> I have a page, with a list of items and an "add" button.
=> When you click on the "add" button, it opens a dialog, with a form to create a new item

Here is what I want : 

1/ When I click the "submit" button inside the dialog, I want the dialog form to get submitted so as to create my new item
2/ Then, the dialog must be closed
3/ At last, the list of items must be refreshed to shows the new item inside of it,  WITHOUT a complete page refresh.
(Juste the content of the page must be refresh).

Here is the code : 
- The list.vue where you can see the list of items and the "add button"
- the Create.vue which contains the dialog


Attachment: add_item_with_modal_f8d498c3.zip


VJ Vinitha Jeyakumar Syncfusion Team July 6, 2021 04:25 PM UTC

Hi Sandra,  
 
Good day to you.  
 
 
We have further validated your query” When I click the "submit" button inside the dialog, I want the dialog form to get submitted so as to create my new item.Then, the dialog must be closed. At last, the list of items must be refreshed to shows the new item inside of it,  WITHOUT a complete page refresh. 
 
Your requirement can be achieved by retrieving the form data in the button click event and then sending the form data to the 'submitBtnClickHandler' method in the parent template, where the form data is used to add the list and then the dialog is hidden. Also, the type of the ejs-button should be changed to 'button' to prevent the page refresh on form submit. We have prepared a sample for your reference, 
 
Code Snippet: 
 
App.vue 
<template> 
    <div> 
        <div id="target" 
             class="control-section; position:relative" 
             style="height: 600px"> 
            <!-- Render Button to open the Dialog --> 
            <ejs-button id="modalBtn" v-on:click.native="btnClick">Add</ejs-button> 
            <!-- Render Dialog --> 
            <ejs-dialog id="dialog" 
                        ref="templateDialog" 
                        :target="target" 
                        :height="height" 
                        :width="width" 
                        :visible="false" 
                        :allowDragging="true" 
                        :content="contentTemplate(horseCollection)" 
                        header="Dialog Form" 
                        :showCloseIcon="true"> 
            </ejs-dialog> 
            <hr /> 
            <table style="width: 100%" id="table"> 
                <tr> 
                    <th>Name</th> 
                    <th>Mail</th> 
                </tr> 
                <tr> 
                    <td>Jill</td> 
                    <td>Smith</td> 
                </tr> 
                <tr> 
                    <td>Eve</td> 
                    <td>Jackson</td> 
                </tr> 
                <tr> 
                    <td>John</td> 
                    <td>Doe</td> 
                </tr> 
            </table> 
        </div> 
    </div> 
</template> 
<script> 
. . . 
. . . 
export default { 
  data: function () { 
    return { 
      target: "#target", 
      height: "100%", 
      width: "435px", 
      contentTemplate: function () { 
        return () => { 
          return { 
            template: { 
              extends: contentTemplate, 
              propsData: { 
                horseCollection: [], 
              }, 
            }, 
          }; 
        }; 
      }, 
    }; 
  }, 
  methods: { 
    btnClick: function () { 
      this.$refs.templateDialog.show(); 
    }, 
    submitBtnClickHandler: function (Name, Mail) { 
      var tableRow = document.createElement('tr'); 
      var td1 =  document.createElement('td'); 
      var td2 =  document.createElement('td'); 
      tableRow.appendChild(td1); 
      tableRow.appendChild(td2); 
      var tab = document.getElementById('table'); 
      tab.appendChild(tableRow); 
      td1.innerHTML = Name; 
      td2.innerHTML = Mail; 
      //dialog is closed by calling hide method. 
      this.$refs.templateDialog.hide(); 
      // submit button action functionalities can be written here. 
    }, 
  }, 
}; 
</script> 
 
Content.vue 
<template> 
    <div> 
        <div class="container"> 
            <form> 
                <div class="row"> 
                    <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> 
                        <br /> 
                        <hr /> 
                        <br /> 
                    </div> 
                </div> 
                <div class="form-group"> 
                    <label>Name: </label> 
                    <input id="input1" ref="name" /> 
                </div> 
                <br /> 
                <div class="form-group"> 
                    <label>Mail: </label> 
                    <input id="input2" ref="mail" /> 
                </div> 
                <br /> 
                <ejs-button type="button" 
                            id="modalBtn1" 
                            v-on:click.native="submitBtnClick">Submit</ejs-button> 
            </form> 
        </div> 
    </div> 
</template> 
 
<script> 
    export default { 
        name: "contentTemplate", 
        props: ["horseCollection", "submitBtnClickHandler"], 
        methods: { 
            submitBtnClick: function () { 
                var Name = this.$refs.name.value; 
                var Mail = this.$refs.mail.value; 
                this.$parent.$parent.submitBtnClickHandler(Name, Mail); 
                //dialog is closed by calling hide method. 
                // submit button action functionalities can be written here. 
            }, 
        }, 
    }; 
</script> 
 
 
Please check the above code snippet and the sample and let us know if it satisfies your requirement.   
  
Regards,  
Vinitha 



SB Sandra Bordier July 6, 2021 09:29 PM UTC

Thank you very much .

I think this is exactly what I need. However, I have a mistake when I try to execute the code : 

"[Vue warn]: Error in created hook: "ReferenceError: submitBtnClickHandler is not defined".

I checked so as to see if I forgot something, but I don't see anything wrong.
Is there any import I need to do to make the " submitBtnClickHandler " work ?

=> Can you check my code and tell me what is wrong ? .

Moreover, I forgot to tell you something :
In fact, the list where I want to show the new created item is not exactly a "list", this is a grid, an "<ejs-grid>" one. 

=> Can you show me how to refresh a grid with a new item is created ?

Thank you very much in advance ! 


Attachment: add_item_with_modal_d06782ee.zip


VJ Vinitha Jeyakumar Syncfusion Team July 7, 2021 01:19 PM UTC

Hi Sandra,   
    
 
We have further validated your query ”Is there any import I need to do to make the submitBtnClickHandler work ? Can you show me how to refresh a grid with a new item is created 
 
Your reference error can be resolved by adding "submitBtnClickHandler” in double-quotes and close with square brackets inside the props of the content.vue file. Also, the form data can be added to the grid using the “addRecord” public method of the grid. We have prepared a sample for your reference, 
 
Code snippet: 
Content.vue  
export default { 
        name: "contentTemplate", 
        props: ["horseCollection", "submitBtnClickHandler"], 
} 
 
App.vue  
submitBtnClickHandler: function (Id, Name) { 
        //form data  
        var d = { 
            CustomerID: Id, 
            CustomerName: Name, 
        }; 
        this.$refs.grid.ej2Instances.addRecord(d, 0);       // update the form data into the Grid by using Grid’s addRecord method  
        this.$refs.templateDialog.hide(); 
    }, 
  
 
Please check the above code snippet and the sample and let us know if it satisfies your requirement.    
 
Regards, 
Vinitha 



SB Sandra Bordier July 7, 2021 09:16 PM UTC

Thank you for your answer.

I changed the props, but new there is a new error : 


"TypeError: this.$parent.$parent.submitBtnClickHandler is not a function"


My code is in the zipFile.

Thank you very much for your help


Attachment: add_item_with_modal_cf53378.zip


VJ Vinitha Jeyakumar Syncfusion Team July 8, 2021 01:21 PM UTC

Hi Sandra,  
 
 
We have further validated your query ”I changed the props, but new there is a new  TypeError: this.$parent.$parent.submitBtnClickHandler is not a function" 
 
We have tried to reproduce the issue in the following ways,  
  • By ensuring the code you have shared with the sample we made.
  • Also ensured the issue by adding “submitBtnClickHandler” in the props.
  • Ensured the issue by running the sample in all major browsers.
But we couldn’t reproduce the issue from our end. We have prepared a sample for your reference,  
 
 
Can you please share us with the runnable issue reproducing sample or please modify the shared sample with the issue reproducing code? 
 
Regards,  
Vinitha 



SB Sandra Bordier July 8, 2021 10:56 PM UTC

Dear support,


I found the solution :)

I replaced :

this.$refs.grid.ej2Instances.addRecord(d, 0);

By :

submitBtnClickHandler: function (Id, Name) {
var d = {
CustomerID: Id,
name: Name,
};
this.dataGrid.unshift(d);
this.dataGrid = [...this.dataGrid];
// this.$refs.grid.ej2Instances.addRecord(d, 0);
//dialog is closed by calling hide method.
this.$refs.templateDialog.hide();
// submit button action functionalities can be written here.*/
},


I've got one last question :

In fact, when I submit my item datas thanks to my dialog form, I would like to :

- Use a webservice(API) to save the submitted datas in a mysql database
- Refresh the content of the whole grid so as to include previous and brand news datas
=> I don't want to just add a temporary line with submitted datas that would disappear if I refresh the whole page.

I really need to populate the grid with all Mysql datas, because it needs to show, for instance, to retrieve the brand new primary key created in the Mysql database (just after form submission) for the new item.

- Then Close the form dialog


Can you help me ?
Thank you in advance !


Attachment: add_item_with_modal_2aaaaf56.zip


SK Sujith Kumar Rajkumar Syncfusion Team July 9, 2021 12:17 PM UTC

Hi Sandra, 
 
Based on your requirement we would like to let you know that the Grid has in-built support for dialog editing and also dialog template editing(that allows you to render your required custom edit controls). So using this you can achieve your requirement of performing dialog edit with Grid. 
 
More details on this can be checked in the below documentation and online demo sample links, 
 
                               https://ej2.syncfusion.com/vue/documentation/grid/edit/#dialoginline-template 
 
                                        https://ej2.syncfusion.com/vue/demos/#/material/grid/dialog-template.html 
 
And also regarding your query to use a web service for saving the Grid edited data in your SQL data base, we suggest you to use the custom binding or remote data binding with adaptor support available with the Grid to achieve the same. We have explained this in detail below, 
 
Custom binding: 
 
If you are using the API calls to perform Grid action from the server, then we suggest you to custom binding approach to bind data in the Grid. With this you can bind data from an API call by providing your own custom queries(as required by your API) and handle all the Grid actions(Sort, Page, Filter, etc. ) with it. The Grid’s custom binding approach is explained below, 
 
For using custom binding, you need to bind the response data(Grid data) returned from your API as an object of result(JSON data source) and count(Total data count) properties and set it to the Grid’s dataSource property. On setting the data source in this format, the ‘dataStateChange’ event will be triggered with corresponding query for every Grid action performed like Paging, Sorting and Filtering.., and the ‘dataSourceChanged’ event will be triggered while performing CRUD action in Grid. So using this you can send the queries in your required format to your API, process and return the result and then assign the returned result to the Grid’s dataSource property as an object of result and count properties. 
 
More details on custom binding with online demo sample can be checked in the below links, 
 
 
 
 
Note:  The ‘dataStateChange’ event will not be triggered on Grid initial render. So for this case you need to return the data in the above mentioned format on initialization and assign it to the Grid’s dataSource property. 
 
Remote data binding: 
 
The EJ2 Grid supports the following adaptors to communicate with the data source in the back-end – Json, URL, OData, ODataV4, Remote Save, Web API and WebMethod adaptor. Each adaptor uses a different way to send and receive requests and response from remote services. They are explained in the below documentation link which you can check for more details, 
 
                               https://ej2.syncfusion.com/vue/documentation/grid/edit/#url-adaptor 
 
You can use the adaptor which best suits your requirement for binding data and performing grid actions(CRUD, Sort, Page, Filter, etc. ) from the server. 
 
Please get back to us if you require any further assistance. 
 
Regards, 
Sujith R 



SB Sandra Bordier July 10, 2021 09:27 AM UTC

Thank you, I am gong to check all the documentations and tell you if it works for me.


In the https://ej2.syncfusion.com/vue/documentation/grid/data-binding/?_ga=2.110355269.1969696766.1625244187-2053838237.1623261141#custom-binding documentation, , "

Perform CRUD operations", you have this :

<template>
<div id="app">
    <ejs-grid :dataSource='data' :allowPaging='true' :pageSettings='pageOptions' :allowSorting='true' :allowGrouping='true' :dataStateChange='dataStateChange'  :editSettings='editSettings' :toolbar='toolbar'>
        <e-columns>
            <e-column field= "OrderID" headerText="Order ID" :isPrimaryKey='true' width="130" textAlign='Right' >e-column>
            <e-column field= "CustomerID" headerText="Customer Name" width="150">e-column>
            <e-column field= "ShipName" headerText="Ship Name" width="200">e-column>
            <e-column field= "ShipCity" headerText="Ship City" width="150">e-column>
        e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin, DataStateChangeEventArgs, Sorts, Sort, Group, Page, DataResult, Toolbar, Edit } from "@syncfusion/ej2-vue-grids";
import { OrderService } from "./order-service";

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: {},
  editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true },
  toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
  pageOptions: { pageSize: 10, pageCount: 4 },
  orderService: new OrderService()
};
  },
  mounted() {
let state = { skip: 0, take: 10 };
this.dataStateChange(state);
  },
  methods:{
dataStateChange: function (state) {
    this.orderService.execute(state).then(( gridData ) => this.data = gridData );
},
dataSourceChanged: function (state) {
if (state.action === 'add') {
  this.orderService.addRecord(state).subscribe(() => state.endEdit());
} else if (state.action === 'edit') {
  this.orderService.updateRecord(state).subscribe(() => state.endEdit());
} else if (state.requestType === 'delete') {
  this.orderService.deleteRecord(state).subscribe(() => state.endEdit());
}
  }
  },
  provide: {
  grid: [Sort, Group, Page, Edit, Toolbar]
  }
});
script>
<style>
 @import "../node_modules/@syncfusion/ej2-vue-grids/styles/material.css";
style>
I have 4 questions : 


1/ Is there a way to get the OderService class please, to check the addRecord and subscribe code ??


2/ I don't understand this line :

import { OrderService } from "./order-service"; order-service does not avec any extension /type of file, as js or php ?

=> Should'nt it be "

import { OrderService } from "./order-service.js";" ?

3/ I don't really get how the "state" property works :
Where are the state.action and state.requestType declared / inizialized ? Do you have a documentation that explains it ?

/ Grid / Data Binding

Data Binding in Vue Grid component

01 Jul 2021 / 15 minutes to read

The Grid uses DataManager which supports both RESTful JSON data services binding and local JavaScript object array binding. The dataSource property can be assigned either with the instance of DataManager or JavaScript object array collection. It supports two kinds of data binding methods:

  • Local data
  • Remote data

To learn about Grid data binding quickly, you can check on this video:

Local Data

To bind local data to the grid, you can assign a JavaScript object array to the dataSource property. The local data source can also be provided as an instance of the DataManager.

By default, DataManager uses JsonAdaptor for local data-binding.

Remote Data

To bind remote data to grid component, assign service data as an instance of DataManager to the dataSource property. To interact with remote data source, provide the endpoint url.

By default, DataManager uses ODataAdaptor for remote data-binding.

Binding with OData Services

OData is a standardized protocol for creating and consuming data. You can retrieve data from OData service using DataManager. You can refer to the following code example of remote data binding using OData service.

Binding with OData v4 services

The ODataV4 is an improved version of OData protocols, and the DataManager can also retrieve and consume OData v4 services. For more details on OData v4 services, refer to the odata documentation. To bind OData v4 service, use the ODataV4Adaptor.

Web API

You can use WebApiAdaptor to bind grid with Web API created using OData endpoint.

<template>
<div id="app">
    <ejs-grid :dataSource="data">
      <e-columns>
        <e-column field='OrderID' headerText='Order ID' textAlign='Right' width=90>e-column>
        <e-column field='CustomerID' headerText='Customer ID' width=120>e-column>
        <e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=90>e-column>
        <e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' type='date' width=120>e-column>
      e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin } from "@syncfusion/ej2-vue-grids";
import { DataManager, WebApiAdaptor } from "@syncfusion/ej2-data";

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: new DataManager({
    url: 'api/Orders',
    adaptor: new WebApiAdaptor(),
    crossDomain: true
  })
};
  }
});
script>
<style>
 @import "../node_modules/@syncfusion/ej2-vue-grids/styles/material.css";
style>

The response object should contain properties Items and Count whose values are a collection of entities and the total count of the entities respectively.

The sample response object should look like below.

{
Items: [{..}, {..}, {..}, ...],
Count: 830
}

Remote Save Adaptor

You may need to perform all Grid Actions in client-side except the CRUD operations, that should be interacted with server-side to persist data. It can be achieved in Grid by using RemoteSaveAdaptor.

Datasource must be set to json property and set RemoteSaveAdaptor to the adaptor property. CRUD operations can be mapped to server-side using updateUrl, insertUrl, removeUrl, batchUrl, crudUrl properties.

You can use the following code example to use RemoteSaveAdaptor in Grid.

<template>
<div id="app">
    <ejs-grid :dataSource="dataSource" :editSettings='editSettings' :toolbar='toolbar'>
      <e-columns>
        <e-column field='OrderID' headerText='Order ID' :isPrimaryKey='true' textAlign='Right' width=90>e-column>
        <e-column field='CustomerID' headerText='Customer ID' width=120>e-column>
        <e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=90>e-column>
        <e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' type='date' width=120>e-column>
      e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin, Toolbar, Edit } from "@syncfusion/ej2-vue-grids";
import { DataManager, RemoteSaveAdaptor } from "@syncfusion/ej2-data";
import { data } from './datasource.js';

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  dataSource: new DataManager({
    json: data,
    adaptor: new RemoteSaveAdaptor,
    insertUrl: '/Home/Insert',
    updateUrl: '/Home/Update',
    removeUrl: '/Home/Delete'
  }),
  editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true },
  toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel']
};
  },
  provide: {
grid: [Edit, Toolbar]
  }
});
script>
<style>
 @import "../node_modules/@syncfusion/ej2-vue-grids/styles/material.css";
style>

The following code example describes the CRUD operations handled at server-side.

public ActionResult Update(OrdersDetails value)
{
    ...
    return Json(value);
}
public ActionResult Insert(OrdersDetails value)
{
    ...
    return Json(value);
}
public ActionResult Delete(int key)
{
    ...
    return Json(data);
}

Custom Adaptor

You can create your own adaptor by extending the built-in adaptors. For the sake of demonstrating custom adaptor approach, we are going to see how to add a serial number for the records by overriding the built-in response processing using the processResponse method of the ODataAdaptor.

Offline mode

On remote data binding, all grid actions such as paging, sorting, editing, grouping, filtering, etc, will be processed on server-side. To avoid post back for every action, set the grid to load all data on initialization and make the actions process in client-side. To enable this behavior, use the offline property of DataManager.

Sending additional parameters

To add a custom parameter to the data request, use the addParams method of Query class. Assign the Query object with additional parameters to the grid query property.

The parameters added using the query property will be sent along with the data request for every grid action.

Handle Http Error

During server interaction from the grid, some server-side exceptions may occur, and you can acquire those error messages or exception details in client-side using the actionFailure event.

The argument passed to the actionFailure Grid event contains the error details returned from the server.

<template>
<div id="app">
    <ejs-grid :dataSource="data" :actionFailure='actionFailure'>
      <e-columns>
        <e-column field='OrderID' headerText='Order ID' textAlign='Right' width=90>e-column>
        <e-column field='CustomerID' headerText='Customer ID' width=120>e-column>
        <e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=90>e-column>
        <e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' type='date' width=120>e-column>
      e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin } from "@syncfusion/ej2-vue-grids";
import { DataManager, ODataAdaptor } from "@syncfusion/ej2-data";

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: new DataManager({
    url: 'http://some.com/invalidUrl',
    adaptor: new ODataAdaptor()
  })
};
  },
  methods: {
actionFailure: function() {
   alert('Server exception: 404 Not found');
}
  }
});
script>
<style>
 @import "../node_modules/@syncfusion/ej2-vue-grids/styles/material.css";
style>

The actionFailure event will be triggered not only for the server errors, but also when there is an exception while processing the grid actions.

Custom Binding

It is possible to handle data processing externally and bind the result to the grid. This help you to provide your own custom data logic. Grid expects an object as the result of the custom logic and the emitted value should be an object with properties result and count.

In this context, we are going to use Ajax from our @syncfusion/ej2-base library for handling remote interaction, you can choose any HTTP client as per your choice.

<template>
<div id="app">
    <ejs-grid :dataSource='data' :allowPaging='true' :pageSettings='pageOptions' :allowSorting='true' :allowGrouping='true' :dataStateChange='dataStateChange'>
        <e-columns>
            <e-column field= "OrderID" headerText="Order ID" width="130" textAlign='Right' >e-column>
            <e-column field= "CustomerID" headerText="Customer Name" width="150">e-column>
            <e-column field= "ShipName" headerText="Ship Name" width="200">e-column>
            <e-column field= "ShipCity" headerText="Ship City" width="150">e-column>
        e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin, DataStateChangeEventArgs, Sorts, Sort, Group, Page, DataResult } from "@syncfusion/ej2-vue-grids";
import { Ajax } from '@syncfusion/ej2-base';

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: {},
  pageOptions: { pageSize: 10, pageCount: 4 },
  orderService: new OrderService()
};
  },
  mounted() {
let state = { skip: 0, take: 10 };
this.dataStateChange(state);
  },
  methods:{
dataStateChange: function (state) {
    this.orderService.execute(state).then(( gridData ) => this.data = gridData );
}
  },
  provide: {
  grid: [Sort, Group, Page]
  }
});
export class OrderService {

public ajax: Ajax = new Ajax({
    type: 'GET', mode: true,
    onFailure: (e: Error) => { return false; }
});

private BASE_URL: string = 'https://js.syncfusion.com/demos/ejServices/Wcf/Northwind.svc/Orders';

public execute(state: DataStateChangeEventArgs): Promise<DataResult> {
    return this.getData(state);
}

private getData(state: DataStateChangeEventArgs): Promise<DataResult> {
    const pageQuery = `$skip=${state.skip}&$top=${state.take}`;
    let sortQuery: string = '';

    if ((state.sorted || []).length) {
        sortQuery = `&$orderby=` + (<any> state).sorted.map((obj: Sorts) => {
            return obj.direction === 'descending' ? `${obj.name} desc` : obj.name;
        }).reverse().join(',');
    }

    this.ajax.url = `${this.BASE_URL}?${pageQuery}${sortQuery}&$inlinecount=allpages&$format=json`;

    return this.ajax.send().then((response: any) => {
        let data: any = JSON.parse(response);
        return <DataResult> { result: data['d']['results'], count: parseInt(data['d']['__count'], 10) };
    });
}
}
script>
<style>
 @import "../node_modules/@syncfusion/ej2-vue-grids/styles/material.css";
style>

Handling Grid actions

For grid actions such as paging, grouping, sorting etc, the dataStateChange event will be invoked. You have to query and resolve data using AJAX in this event based on the state arguments.

<template>
<div id="app">
    <ejs-grid :dataSource='data' :allowPaging='true' :pageSettings='pageOptions' :allowSorting='true' :allowGrouping='true' :dataStateChange='dataStateChange'>
        <e-columns>
            <e-column field= "OrderID" headerText="Order ID" width="130" textAlign='Right' >e-column>
            <e-column field= "CustomerID" headerText="Customer Name" width="150">e-column>
            <e-column field= "ShipName" headerText="Ship Name" width="200">e-column>
            <e-column field= "ShipCity" headerText="Ship City" width="150">e-column>
        e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin, DataStateChangeEventArgs, Sorts, Sort, Group, Page, DataResult } from "@syncfusion/ej2-vue-grids";
import { Ajax } from '@syncfusion/ej2-base';

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: {},
  pageOptions: { pageSize: 10, pageCount: 4 },
  orderService: new OrderService()
};
  },
  mounted() {
let state = { skip: 0, take: 10 };
this.dataStateChange(state);
  },
  methods:{
dataStateChange: function (state) {
    this.orderService.execute(state).then(( gridData ) => this.data = gridData );
}
  },
  provide: {
  grid: [Sort, Group, Page]
  }
});
export class OrderService {

public ajax: Ajax = new Ajax({
    type: 'GET', mode: true,
    onFailure: (e: Error) => { return false; }
});
private BASE_URL: string = 'https://js.syncfusion.com/demos/ejServices/Wcf/Northwind.svc/Orders';
public execute(state: DataStateChangeEventArgs): Promise<DataResult> {
    return this.getData(state);
}
private getData(state: DataStateChangeEventArgs): Promise<DataResult> {
    const pageQuery = `$skip=${state.skip}&$top=${state.take}`;
    let sortQuery: string = '';
    if ((state.sorted || []).length) {
        sortQuery = `&$orderby=` + (state).sorted.map((obj: Sorts) => {
            return obj.direction === 'descending' ? `${obj.name} desc` : obj.name;
        }).reverse().join(',');
    }
    this.ajax.url = `${this.BASE_URL}?${pageQuery}${sortQuery}&$inlinecount=allpages&$format=json`;
    return this.ajax.send().then((response: any) => {
        let data: any = JSON.parse(response);
        return { result: data['d']['results'], count: parseInt(data['d']['__count'], 10) };
    });
}
  }
script>
<style>
 @import "../node_modules/@syncfusion/ej2-vue-grids/styles/material.css";
style>

Perform CRUD operations

The dataSourceChanged event will be triggered for updating the grid data. You can perform the save operation based on the event arguments and you need to call the endEdit method to indicate the completion of save operation.

<template>
<div id="app">
    <ejs-grid :dataSource='data' :allowPaging='true' :pageSettings='pageOptions' :allowSorting='true' :allowGrouping='true' :dataStateChange='dataStateChange'  :editSettings='editSettings' :toolbar='toolbar'>
        <e-columns>
            <e-column field= "OrderID" headerText="Order ID" :isPrimaryKey='true' width="130" textAlign='Right' >e-column>
            <e-column field= "CustomerID" headerText="Customer Name" width="150">e-column>
            <e-column field= "ShipName" headerText="Ship Name" width="200">e-column>
            <e-column field= "ShipCity" headerText="Ship City" width="150">e-column>
        e-columns>
    ejs-grid>
div>
template>
<script>
import Vue from "vue";
import { GridPlugin, DataStateChangeEventArgs, Sorts, Sort, Group, Page, DataResult, Toolbar, Edit } from "@syncfusion/ej2-vue-grids";
import { OrderService } from "./order-service";

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: {},
  editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true },
  toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
  pageOptions: { pageSize: 10, pageCount: 4 },
  orderService: new OrderService()
};
  },
  mounted() {
let state = { skip: 0, take: 10 };
this.dataStateChange(state);
  },
  methods:{
dataStateChange: function (state) {
    this.orderService.execute(state).then(( gridData ) => this.data = gridData );
},
dataSourceChanged: function (state) {
if (state.action === 'add') {
  this.orderService.addRecord(state).subscribe(() => state.endEdit());
} else if (state.action === 'edit') {
  this.orderService.updateRecord(state).subscribe(() => state.endEdit());
} else if (state.requestType === 'delete') {
  this.orderService.deleteRecord(state).subscribe(() => state.endEdit());
}


4/ And in this example : 


<template>
<div id="app">
    <ejs-grid :dataSource='data' :allowPaging='true' :pageSettings='pageOptions' :allowSorting='true' :allowGrouping='true' :dataStateChange='dataStateChange'>
        <e-columns>
            <e-column field= "OrderID" headerText="Order ID" width="130" textAlign='Right' ></e-column>
            <e-column field= "CustomerID" headerText="Customer Name" width="150"></e-column>
            <e-column field= "ShipName" headerText="Ship Name" width="200"></e-column>
            <e-column field= "ShipCity" headerText="Ship City" width="150"></e-column>
        </e-columns>
    </ejs-grid>
</div>
</template>
<script>
import Vue from "vue";
import { GridPlugin, DataStateChangeEventArgs, Sorts, Sort, Group, Page, DataResult } from "@syncfusion/ej2-vue-grids";
import { Ajax } from '@syncfusion/ej2-base';

Vue.use(GridPlugin);

export default Vue.extend({
  data() {
return {
  data: {},
  pageOptions: { pageSize: 10, pageCount: 4 },
  orderService: new OrderService()
};
  },
  mounted() {
let state = { skip: 0, take: 10 };
this.dataStateChange(state);
  },
  methods:{
dataStateChange: function (state) {
    this.orderService.execute(state).then(( gridData ) => this.data = gridData );
}
  },
  provide: {
  grid: [Sort, Group, Page]
  }
});


How does the "then" from "this.orderService.execute(state).then(( gridData ) => this.data = gridData );

" work ?
Why is it different from the "this.orderService.addRecord(state).subscribe(() => state.endEdit());

from the previous example ? In fact, I don't understand what I have to use to add new datas is my grid.

In a creation case, do I have to use this.orderService.execute(state).then(( gridData ) => this.data = gridData  or this.orderService.addRecord(state).subscribe(() => state.endEdit() ?



Best regards :)



SB Sandra Bordier July 10, 2021 01:08 PM UTC

And please where do I declare / import the dataSourceChanged ?


I can't see it :

<ejs-grid :dataSource='data' :allowPaging='true' :pageSettings='pageOptions' :allowSorting='true' :allowGrouping='true' :dataStateChange='dataStateChange'>

or here :

import { GridPlugin, DataStateChangeEventArgs, Sorts, Sort, Group, Page, DataResult,


or in the mounted part :

mounted() { let state = { skip: 0, take: 10 }; this.dataStateChange(state); },



SK Sujith Kumar Rajkumar Syncfusion Team July 12, 2021 09:17 AM UTC

Hi Sandra, 
 
Please find the response for your queries below, 
 
Query – 1: “Is there a way to get the OrderService class please, to check the addRecord and subscribe code ??” 
Query – 2: “I don't understand this line - import { OrderService } from "./order-service"; order-service does not avec any extension /type of file, as js or php ?” 
 
The “OrderService” mentioned in the specified line is a service file that is written for handling the actions like, CRUD, Sort, Page, etc in the Grid. So we have prepared a Grid sample with local server(for fetching data) to demonstrate this case for your reference. You can find it below, 
 
 
Note: Before launching the above application, the express server needs to be started using the ‘node server.js’ command from the application’s root folder and then the Vue application can be launched using ‘npm run dev’ command. These actions need to be performed after installing the node modules. 
 
Query – 3: “I don't really get how the "state" property works. Where are the state.action and state.requestType declared / inizialized ? Do you have a documentation that explains it ?” 
 
As mentioned in the previous update when the custom binding approach is implemented in the Grid the dataStateChange(Grid action)/dataSourceChanged(CRUD action) event will be triggered for the corresponding action along with the query details returned in the event arguments. The argument is accessed with the name ‘state’ in the documentation and it will return the corresponding action details from the source with which you can handle the action in your server and return back the response to the Grid. This case can be checked in the above shared sample for reference.  
 
So when the CRUD action is performed in the Grid, the action details will be returned in the dataSourceChanged event as shown in the below image, 
 
 
 
And in this event you can update the details in your server and on success of this action you need to call the state’s(The dataSourceChanged event argument) endEdit method in order to update the changes in the Grid(This will trigger the dataStateChange event which will fetch the updated data from the server). For this case we have used the ‘OrderService’ to handle these operations. 
 
Query – 4: “How does the ‘then’ from ‘this.orderService.execute(state).then(( gridData ) => this.data = gridData );’ work ? Why is it different from the "this.orderService.addRecord(state).subscribe(() => state.endEdit()); from the previous example ?” 
 
For the Grid action like, Sort, Page, etc., you need to perform the corresponding action in your server(with the returned queries) and then bind the returned data to the Grid. So here we have used the following code – “this.orderService.execute(state).then(( gridData ) => this.data = gridData );”. And for CRUD action, once you have updated the details in your server you need to call the argument’s endEdit method which will in turn identify that the CRUD action has been completed and will trigger the dataStateChange event again for fetching the updated data from the server. 
 
We have used the service - ‘OrderService’ here to handle these actions but you do not have to use the same thing as you can use your own approach and handle these cases. So please check the above shared sample for understanding the workflow implemented here for reference. 
 
Query – 5: “And please where do I declare / import the dataSourceChanged ?” 
 
The dataSourceChanged is a Grid event so you can define it same like the dataStateChange is defined which is demonstrated below for your reference, 
 
<template> 
    <ejs-grid ref="grid" :dataSource="data" :dataSourceChanged="dataSourceChanged" :dataStateChange="dataStateChange"></ejs-grid> 
</template> 
<script> 
import Vue from "vue"; 
import { GridPlugin, Toolbar, Edit } from "@syncfusion/ej2-vue-grids"; 
import { getOrders, addOrder, updateOrder, deleteOrder } from "./orderService"; 
 
Vue.use(GridPlugin); 
 
export default { 
  name: 'app', 
  data() { 
              ... 
  }, 
  methods: { 
    dataStateChange: function (state) { 
              ... 
    }, 
    dataSourceChanged: function (state) { 
              ... 
    } 
  } 
} 
</script> 
 
Regards, 
Sujith R 


Loader.
Up arrow icon