- Binding local data
- Binding remote data
- Use edit template in foreign key column
- Customize filter UI of foreign key column
- Use filter bar template in foreign key column
- Perform aggregation in foreign key column
- Render foreign key value in column template
- Enable multiple foreign key columns
- Edit template in foreign key column using remote data
Contact Support
Foreign key column in Vue Grid component
7 May 202524 minutes to read
The Foreign key column in the Syncfusion® Grid control allows you to display related data from a foreign key data source in a column within the grid. This feature is particularly useful when you have a column in the grid that represents a foreign key relationship with another data source.
To enable and integrate the foreign key column in the EJ2 Vue Grid control, follow these steps:
1.Inject the ForeignKeyService in the provider section of the AppModule.
import { GridPlugin, ForeignKey } from "@syncfusion/ej2-vue-grids";
export default {
// remaining code
provide: {
grid: [ForeignKey]
}
}
2.Define the foreign key column in the grid using the following properties:
-
dataSource: Specifies the foreign data source that contains the related data.
-
foreignKeyField: Maps the column name in the grid to the field in the foreign data source that represents the foreign key relationship.
-
foreignKeyValue: Specifies the field from the foreign data source that should be displayed in the grid as the related data.
<e-column field='EmployeeID' headerText='Employee Name' width=120 foreignKeyField='EmployeeID' foreignKeyValue='FirstName' :dataSource='employeeData'></e-column>
The
foreignKeyField
property should match the name of the field in the foreign data source that represents the foreign key relationship, and theforeignKeyValue
property should specify the field from the foreign data source that should be displayed in the grid as the related data.
Binding local data
The Syncfusion® Grid component provides a convenient way to bind local data to a foreign key column. This allows you to display related data from a local data source within the grid. Here’s an example of how to bind local data to a Foreign Key column in Syncfusion® Grid:
In this example, data is the local data source for the Grid, and employeeData is the local data source for the foreign key column. The field
property of the e-column component is set to EmployeeID which represents the foreign key value in the data. The foreignKeyValue
property is set to FirstName which represents the field name in the employeeData that you want to display in the foreign key column.
<template>
<div id="app">
<ejs-grid :dataSource='data' height='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' width=100 foreignKeyField='EmployeeID'
foreignKeyValue='FirstName' :dataSource='employeeData'></e-column>
<e-column field='Freight' headerText='Freight' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { data, employeeData } from './datasource.js';
provide('grid', [ForeignKey]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid :dataSource='data' height='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' width=100 foreignKeyField='EmployeeID' foreignKeyValue='FirstName' :dataSource='employeeData'></e-column>
<e-column field='Freight' headerText='Freight' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130 ></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script>
import { GridComponent, ColumnsDirective, ColumnDirective, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { data, employeeData } from './datasource.js';
export default {
name: "App",
components: {
"ejs-grid":GridComponent,
"e-columns":ColumnsDirective,
"e-column":ColumnDirective
},
data() {
return {
data: data,
employeeData: employeeData
};
},
provide: {
grid: [ForeignKey]
}
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Binding remote data
The Foreign key column in Syncfusion® Grid allows you to bind remote data for a foreign key column. You can assign the service data as an instance of DataManager
to the dataSource
property, and provide the endpoint URL
as the data source URL.
This example demonstrates how to use the foreign key column with remote data binding using the WebApiAdaptor in the grid:
<template>
<div id="app">
<ejs-grid :dataSource='data' height='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' width=100 foreignKeyField='EmployeeID' foreignKeyValue='FirstName' :dataSource='employeeData'></e-column>
<e-column field='Freight' headerText='Freight' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130 ></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { DataManager, WebApiAdaptor } from "@syncfusion/ej2-data";
const data = new DataManager({
url: "https://services.syncfusion.com/vue/production/api/Orders",
adaptor: new WebApiAdaptor(),
crossDomain: true
})
const employeeData = new DataManager({
url: "https://services.syncfusion.com/vue/production/api/employees",
adaptor: new WebApiAdaptor(),
crossDomain: true
})
provide('grid', [ForeignKey]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid :dataSource='data' height='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' width=100 foreignKeyField='EmployeeID' foreignKeyValue='FirstName' :dataSource='employeeData'></e-column>
<e-column field='Freight' headerText='Freight' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130 ></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script>
import { GridComponent, ColumnsDirective, ColumnDirective, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { DataManager, WebApiAdaptor } from "@syncfusion/ej2-data";
export default {
name: "App",
components: {
"ejs-grid":GridComponent,
"e-columns":ColumnsDirective,
"e-column":ColumnDirective
},
data() {
return {
data: new DataManager({
url: "https://services.syncfusion.com/vue/production/api/Orders",
adaptor: new WebApiAdaptor(),
crossDomain: true
}),
employeeData: new DataManager({
url: "https://services.syncfusion.com/vue/production/api/employees",
adaptor: new WebApiAdaptor(),
crossDomain: true
})
};
},
provide: {
grid: [ForeignKey]
}
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
- For remote data, the sorting and grouping is done based on column.foreignKeyField instead of column.foreignKeyValue.
- If column.foreignKeyField is not defined, then the column uses column.field.
Use edit template in foreign key column
The Syncfusion® Grid provides support for using an edit template in a foreign key column. By default, a dropdown component is used for editing foreign key column. However, you can render a different component for editing by using the column.edit property. Here’s an example that demonstrates how to use an edit template in a foreign key column:
In this example, an AutoComplete component is rendered as the edit template for the “EmployeeID” foreign key column. The dataSource property of the AutoComplete component is set to the employees data, and the fields property is configured to display the “FirstName” field as the value.
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :editSettings='editoption' :toolbar='toolbar' height='270px'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName'
:edit='edit' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { createElement } from '@syncfusion/ej2-base';
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, Edit, Toolbar, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { AutoComplete } from "@syncfusion/ej2-dropdowns";
import { DataManager, Query } from '@syncfusion/ej2-data';
import { data, employeeData } from './datasource.js';
const toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const editoption = { allowEditing: true };
var autoComplete;
const edit = {
create: () => { // to create input element
return createElement('input');
},
read: () => { // return edited value to update data source
let value = new DataManager(employeeData).executeLocal(new Query().where('FirstName', 'equal', autoComplete.value));
return value.length && value[0]['EmployeeID']; // to convert foreign key value to local value.
},
destroy: () => { // to destroy the custom component.
autoComplete.destroy();
},
write: (args) => { // to show the value for date picker
autoComplete = new AutoComplete({
dataSource: employeeData,
fields: { value: args.column.foreignKeyValue },
value: args.foreignKeyData[0][args.column.foreignKeyValue]
});
autoComplete.appendTo(args.element);
}
};
provide('grid', [Edit, ForeignKey, Toolbar]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :editSettings='editoption' :toolbar='toolbar' height='270px'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName'
:edit='edit' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script>
import { createElement } from '@syncfusion/ej2-base';
import { GridComponent, ColumnsDirective, ColumnDirective, Edit, Toolbar, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { AutoComplete } from "@syncfusion/ej2-dropdowns";
import { DataManager, Query } from '@syncfusion/ej2-data';
import { data, employeeData } from './datasource.js';
var autoComplete;
export default {
name: "App",
components: {
"ejs-grid": GridComponent,
"e-columns": ColumnsDirective,
"e-column": ColumnDirective
},
data: () => {
return {
data: data,
employeeData: employeeData,
toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
editoption: { allowEditing: true },
edit: {
create: () => { // to create input element
return createElement('input');
},
read: () => { // return edited value to update data source
let value = new DataManager(employeeData).executeLocal(new Query().where('FirstName', 'equal', autoComplete.value));
return value.length && value[0]['EmployeeID']; // to convert foreign key value to local value.
},
destroy: () => { // to destroy the custom component.
autoComplete.destroy();
},
write: (args) => { // to show the value for date picker
autoComplete = new AutoComplete({
dataSource: employeeData,
fields: { value: args.column.foreignKeyValue },
value: args.foreignKeyData[0][args.column.foreignKeyValue]
});
autoComplete.appendTo(args.element);
}
},
};
},
provide: {
grid: [Edit, ForeignKey, Toolbar]
},
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Customize filter UI of foreign key column
The Syncfusion® Grid allows you to customize the filtering user interface (UI) for foreign key columns by using the column.filter property. By default, a dropdown component is used for filtering foreign key columns. However, you can create your own custom filtering UI by specifying a template function for the column.filter
property. Here’s an example that demonstrates how to create a custom filtering UI in a foreign key column:
In this example, a DropDownList component is rendered as the filter UI for the “EmployeeID” foreign key column. The dataSource property of the DropDownList component is set to the employees data, and the fields property is configured to display the FirstName field as the text and EmployeeID field as the value. The value
property is set to the current filter value of the column.
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :allowFiltering='true' :filterSettings='filteroption' height='270px'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName'
:filter='filter' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { createElement } from '@syncfusion/ej2-base';
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, Edit, Toolbar, ForeignKey, Filter } from "@syncfusion/ej2-vue-grids";
import { DropDownList } from "@syncfusion/ej2-dropdowns";
import { DataManager } from '@syncfusion/ej2-data';
import { data, employeeData } from './datasource.js';
let dropInstance;
const filteroption = { type: 'Menu' };
const filter = {
ui: {
create: (args) => {
let flValInput = createElement('input', { className: 'flm-input' });
args.target.appendChild(flValInput);
dropInstance = new DropDownList({
dataSource: new DataManager(employeeData),
fields: { text: 'FirstName', value: 'EmployeeID' },
placeholder: 'Select a value',
popupHeight: '200px'
});
dropInstance.appendTo(flValInput);
},
write: (args) => {
dropInstance.text = args.filteredValue || '';
},
read: (args) => {
args.fltrObj.filterByColumn(args.column.field, args.operator, dropInstance.text);
}
}
}
provide('grid', [Filter, ForeignKey, Edit, Toolbar]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :allowFiltering='true' :filterSettings='filteroption' height='270px' >
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName' :filter='filter' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script>
import { createElement } from '@syncfusion/ej2-base';
import { GridComponent, ColumnsDirective, ColumnDirective, Edit, Toolbar, ForeignKey, Filter } from "@syncfusion/ej2-vue-grids";
import { DropDownList } from "@syncfusion/ej2-dropdowns";
import { DataManager } from '@syncfusion/ej2-data';
import { data,employeeData } from './datasource.js';
let dropInstance;
export default {
name: "App",
components: {
"ejs-grid":GridComponent,
"e-columns":ColumnsDirective,
"e-column":ColumnDirective
},
data: () => {
return {
data: data,
employeeData: employeeData,
filteroption: { type: 'Menu' },
filter: {
ui: {
create: (args) => {
let flValInput = createElement('input', { className: 'flm-input' });
args.target.appendChild(flValInput);
dropInstance = new DropDownList({
dataSource: new DataManager(employeeData),
fields: { text: 'FirstName', value: 'EmployeeID' },
placeholder: 'Select a value',
popupHeight: '200px'
});
dropInstance.appendTo(flValInput);
},
write: (args) => {
dropInstance.text = args.filteredValue || '';
},
read: (args) => {
args.fltrObj.filterByColumn(args.column.field, args.operator,dropInstance.text);
}
}
},
};
},
provide: {
grid: [Filter, ForeignKey, Edit, Toolbar]
}
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Use filter bar template in foreign key column
You can use the filter bar template in a foreign key column in Grid by defining the column.filterBarTemplate property. This allows you to customize the filter bar for the foreign key column with a custom component or HTML template. Here’s an example that demonstrates how to use a filter bar template in a foreign key column:
In this example, the “EmployeeID” column is a foreign key column, and the filter function is used as the filter bar template for this column. The filter
function can be defined in your component code and should return the desired component or HTML template for the filter bar. The column header shows the custom filter bar template and you can select filter value by using the drop down options.
<template>
<div id="app">
<ejs-grid id='grid' ref='grid' :dataSource='data' :allowFiltering='true' height='270px' >
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName' :filterBarTemplate='templateOptions' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide, ref } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, Filter,ForeignKey } from "@syncfusion/ej2-vue-grids";
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { data, employeeData } from './datasource.js'
const grid = ref(null);
const templateOptions = {
create: function () {
const dropdown = document.createElement('input');
dropdown.id = 'EmployeeID';
return dropdown;
},
write: function () {
let DropDownListObj = new DropDownList({
dataSource: employeeData,
fields: { text: 'FirstName', value: 'FirstName' },
placeholder: 'Select a value',
popupHeight: '200px',
change: function (e) {
var gridObj = grid.value.ej2Instances;
if (e.value == 'All') {
gridObj.removeFilteredColsByField('FirstName');
} else {
gridObj.filterByColumn('EmployeeID', 'equal', e.value);
}
}
});
DropDownListObj.appendTo('#EmployeeID');
}
}
provide('grid', [Filter, ForeignKey]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :allowFiltering='true' height='260px' >
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
<e-aggregates>
<e-aggregate>
<e-columns>
<e-column field="EmployeeID" type="Custom" :customAggregate='customAggregateFn' :footerTemplate='footerTemplate'></e-column>
</e-columns>
</e-aggregate>
</e-aggregates>
</ejs-grid>
</div>
</template>
<script setup>
import { provide, ref } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, AggregateDirective as EAggregate, AggregatesDirective as EAggregates, Aggregate ,ForeignKey, Filter } from "@syncfusion/ej2-vue-grids";
import { getValue } from "@syncfusion/ej2-base";
import { getForeignData } from "@syncfusion/ej2-grids";
import { data, employeeData } from './datasource.js';
import { createApp } from "vue";
const app = createApp();
const grid = ref(null);
const employeeData = employeeData;
const footerTemplate = function () {
return {
template: app.component('customTemplate', {
template: `<span>Count of Margaret: </span>`,
data() { return { data: { data: {} } }; }
})
}
}
const customAggregateFn = function (data, column) {
return data.result.filter((obj) => {
return getValue('FirstName', getForeignData(grid.value.getColumnByField(column.field), obj)[0]) === 'Margaret';
}).length;
}
provide('grid', [Aggregate, ForeignKey, Filter]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Perform aggregation in foreign key column
By default, aggregations are not supported in a foreign key column in the Syncfusion® Grid. However, you can achieve aggregation for a foreign key column by using customAggregate.
To perform aggregation in a foreign key column, follow these steps:
1.Define a foreign key column in the Grid.
2.Implement a custom aggregate function to calculate the aggregation for the foreign key column.
3.Set the customAggregate property of the column to the custom aggregate function.
Here’s an example that demonstrates how to perform aggregation in a foreign key column:
In the provided example, the customAggregateFn
function is used to filter the data based on the FirstName field of the foreign key column, using the getForeignData
internal function. The function then counts the occurrences of Margaret. The result is displayed in the grid’s footer template using the ng-template with the #footerTemplate
reference.
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :allowFiltering='true' height='260px' >
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
<e-aggregates>
<e-aggregate>
<e-columns>
<e-column field="EmployeeID" type="Custom" :customAggregate='customAggregateFn' :footerTemplate='footerTemplate'></e-column>
</e-columns>
</e-aggregate>
</e-aggregates>
</ejs-grid>
</div>
</template>
<script setup>
import { provide, ref } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, AggregateDirective as EAggregate, AggregatesDirective as EAggregates, Aggregate ,ForeignKey, Filter } from "@syncfusion/ej2-vue-grids";
import { getValue } from "@syncfusion/ej2-base";
import { getForeignData } from "@syncfusion/ej2-grids";
import { data, employeeData } from './datasource.js';
import { createApp } from "vue";
const app = createApp();
const grid = ref(null);
const employeeData = employeeData;
const footerTemplate = function () {
return {
template: app.component('customTemplate', {
template: `<span>Count of Margaret: {{data.Custom}}</span>`,
data() { return { data: { data: {} } }; }
})
}
}
const customAggregateFn = function (data, column) {
return data.result.filter((obj) => {
return getValue('FirstName', getForeignData(grid.value.getColumnByField(column.field), obj)[0]) === 'Margaret';
}).length;
}
provide('grid', [Aggregate, ForeignKey, Filter]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid ref='grid' :dataSource='data' :allowFiltering='true' height='260px' >
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='EmployeeID' headerText='Employee Name' :dataSource='employeeData' foreignKeyValue='FirstName' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Center' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
<e-aggregates>
<e-aggregate>
<e-columns>
<e-column field="EmployeeID" type="Custom" :customAggregate='customAggregateFn' :footerTemplate='footerTemplate'></e-column>
</e-columns>
</e-aggregate>
</e-aggregates>
</ejs-grid>
</div>
</template>
<script>
import { GridComponent, ColumnsDirective, ColumnDirective, AggregatesDirective, AggregateDirective, Aggregate ,ForeignKey, Filter } from "@syncfusion/ej2-vue-grids";
import { getValue } from "@syncfusion/ej2-base";
import { getForeignData } from "@syncfusion/ej2-grids";
import { data, employeeData } from './datasource.js';
import { createApp } from "vue";
const app = createApp();
export default {
name: "App",
components: {
"ejs-grid":GridComponent,
"e-columns":ColumnsDirective,
"e-column":ColumnDirective,
"e-aggregates":AggregatesDirective,
"e-aggregate":AggregateDirective
},
data: () => {
return {
data: data,
employeeData: employeeData,
footerTemplate: function () {
return {
template: app.component('customTemplate', {
template: `<span>Count of Margaret: {{data.Custom}}</span>`,
data() { return { data: { data: {} } }; }
})
}
},
};
},
methods: {
customAggregateFn: function (data, column) {
return data.result.filter((obj) => {
return getValue('FirstName', getForeignData(this.$refs.grid.getColumnByField(column.field), obj)[0]) === 'Margaret';
}).length;
}
},
provide: {
grid: [Aggregate, ForeignKey, Filter],
},
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Render foreign key value in column template
The Syncfusion® Vue Grid allows for rendering foreign key values within a column template
, enhancing the display of related data in a clear format. This feature is particularly useful when you want to show a more meaningful representation of a foreign key instead of its underlying value.
To render foreign key values in a column template, you need to define a template for the column using the template property. The template
property can accept either an HTML element or a function that returns the desired HTML element.
The following example demonstrates how to render foreign key values in a column template
within the Grid:
<template>
<div id="app">
<ejs-grid ref="grid" id="grid" :dataSource="data" height="315px">
<e-columns>
<e-column field="OrderID" headerText="Order ID" textAlign="Right" width="90"></e-column>
<e-column field="CustomerID" headerText="Customer Name" width="150" foreignKeyField="CustomerID" foreignKeyValue="ContactName" :dataSource="customerData" :template="'radioTemplate'" >
</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" type="date" format="yMd" width="120"></e-column>
</e-columns>
<template v-slot:radioTemplate="{ data }">
<a href="javascript:void(0)" @click="navToAccount(data.OrderID,$event)">{{ data.foreignKeyData.ContactName }}</a>
</template>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { orderDetails, customerData } from './datasource';
const data=orderDetails;
const navToAccount = (id) => {
window.history.pushState("", "changed", `../Account/AccountDetail.cshtml?custid=0&accountId=${id}`);
};
provide('grid', [ForeignKey]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid ref="grid" id="grid" :dataSource="data" height="315px">
<e-columns>
<e-column field="OrderID" headerText="Order ID" textAlign="Right" width="90"></e-column>
<e-column field="CustomerID" headerText="Customer Name" width="150" foreignKeyField="CustomerID" foreignKeyValue="ContactName" :dataSource="customerData" :template="'radioTemplate'" >
</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" type="date" format="yMd" width="120"></e-column>
</e-columns>
<template v-slot:radioTemplate="{ data }">
<a href="javascript:void(0)" @click="navToAccount(data.OrderID,$event)">{{ data.foreignKeyData.ContactName }}</a>
</template>
</ejs-grid>
</div>
</template>
<script>
import { GridComponent, ColumnsDirective, ColumnDirective, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { orderDetails, customerData } from './datasource';
export default {
name: "App",
components: {
"ejs-grid": GridComponent,
"e-columns": ColumnsDirective,
"e-column": ColumnDirective,
},
data() {
return {
data:orderDetails,
customerData: customerData
};
},
methods: {
navToAccount(Id) {
window.history.pushState("", "changed", `../Account/AccountDetail.cshtml?custid=0&accountId=${Id}`);
}
},
provide() {
return {
grid: [ForeignKey]
};
}
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Enable multiple foreign key columns
The Syncfusion® Grid component supports the feature of enabling multiple foreign key columns with editing options. This allows users to display columns from foreign data sources in the Grid component.
In the following example, Customer Name and Ship City are foreign key columns that display the ContactName and City columns from foreign data.
<template>
<div id="app">
<ejs-grid :dataSource='orderDetails' :editSettings='editOptions' :toolbar='toolbarItems' height='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' :validationRules='orderidrules'
:isPrimaryKey='true' width=100></e-column>
<e-column field='CustomerID' headerText='Customer Name' width=120 foreignKeyValue='ContactName'
foreignKeyField="CustomerID" :dataSource='customerData' :validationRules='orderidrules'></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' editType='numericedit' width=80
format='C2'></e-column>
<e-column field='EmployeeID' headerText='Ship City' width=120 foreignKeyValue='City' foreignKeyField="EmployeeID"
:dataSource='employeeData' :validationRules='orderidrules'></e-column>
<e-column field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, Edit, Toolbar, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { orderDetails, customerData, employeeData } from './datasource.js';
const orderDetails = orderDetails;
const customerData = customerData;
const employeeData = employeeData;
const toolbarItems = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const editOptions = { allowEditing: true, allowAdding: true, allowDeleting: true };
const orderidrules = { required: true };
provide('grid', [Edit, Toolbar, ForeignKey]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";</style>
<template>
<div id="app">
<ejs-grid :dataSource='orderDetails' :editSettings='editOptions' :toolbar='toolbarItems' height='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' :validationRules='orderidrules' :isPrimaryKey='true' width=100></e-column>
<e-column field='CustomerID' headerText='Customer Name' width=120 foreignKeyValue='ContactName' foreignKeyField="CustomerID" :dataSource='customerData' :validationRules='orderidrules'></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' editType='numericedit' width=80 format='C2'></e-column>
<e-column field='EmployeeID' headerText='Ship City' width=120 foreignKeyValue='City' foreignKeyField="EmployeeID" :dataSource='employeeData' :validationRules='orderidrules'></e-column>
<e-column field='ShipCountry' headerText='Ship Country' editType='dropdownedit' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script>
import { GridComponent, ColumnsDirective, ColumnDirective, Edit, Toolbar, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { orderDetails, customerData, employeeData } from './datasource.js';
export default {
name: "App",
components: {
"ejs-grid":GridComponent,
"e-columns":ColumnsDirective,
"e-column":ColumnDirective
},
data() {
return {
orderDetails: orderDetails,
customerData: customerData,
employeeData: employeeData,
toolbarItems: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
editOptions: { allowEditing: true, allowAdding: true, allowDeleting: true },
orderidrules: { required: true },
};
},
provide: {
grid: [Edit, Toolbar, ForeignKey]
}
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Edit template in foreign key column using remote data
The Syncfusion Vue Grid allows you to customize the edit template for foreign key columns when using remote data. By default, a DropDownList component is used for editing foreign key column. However, you can render a different component by configuring the column.edit property.
This example demonstrates how to use an edit template in a foreign key column with remote data. In this case, an AutoComplete component is rendered as the edit template for the EmployeeID foreign key column. The dataSource property of the AutoComplete component is set to the employees data, and the field property is configured to display the FirstName field as the value. Follow the steps below to achieve this:
Step 1: Open Visual Studio and create an Vue and ASP.NET Core project named EditTemplate. To create an Vue and ASP.NET Core application, follow the documentation link for detailed steps.
Step 2 : Create a simple Grid by following the Getting Started documentation link.
Step 3: In your Vue component file (App.vue), include the following styles to import necessary Syncfusion styles:
@import '../node_modules/@syncfusion/ej2-base/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css';
@import '../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css';
Step 4: In your Vue component file (e.g., App.vue), define the Grid with the necessary configurations, including a foreign key column for EmployeeID, and implement the required logic to manage its behavior.
<template>
<div id="app">
<ejs-grid :dataSource='data' :toolbar="toolbar" :editSettings="editSettings" height="250">
<e-columns>
<e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right' isPrimaryKey="true" :validationRules='orderIDRules'></e-column>
<e-column field="EmployeeID" headerText="Employee Name" foreignKeyValue="FirstName" foreignKeyField="EmployeeID" :dataSource="employeeData" :edit='edit' width="120"></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script setup>
import { provide } from "vue";
import { createElement, getValue } from '@syncfusion/ej2-base';
import { GridComponent as EjsGrid, ColumnDirective as EColumn, ColumnsDirective as EColumns, Edit, Toolbar, ForeignKey } from "@syncfusion/ej2-vue-grids";
import { DataManager, UrlAdaptor } from "@syncfusion/ej2-data";
import { AutoComplete } from '@syncfusion/ej2-dropdowns';
const data = new DataManager({
url: 'https://localhost:****/api/Grid',
insertUrl: 'https://localhost:****/api/Grid/Insert',
updateUrl: 'https://localhost:****/api/Grid/Update',
removeUrl: 'https://localhost:****/api/Grid/Remove',
adaptor: new UrlAdaptor(),
});
const employeeData = new DataManager({
url: "https://localhost:****/api/Grid/employees",
adaptor: new UrlAdaptor(),
crossDomain: true
})
const editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true };
const toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
const orderIDRules = { required: true, number: true };
var autoComplete;
const edit = {
create: () => {
return createElement('input');
},
read: () => {
return autoComplete.itemData?.employeeID;
},
destroy: () => {
autoComplete.destroy();
},
write: (args) => {
let selectedValue = args.foreignKeyData?.length > 0 ? args.foreignKeyData[0]['firstName'] : '';
autoComplete = new AutoComplete({
dataSource: employeeData,
fields: { value: 'firstName' },
value: selectedValue
});
autoComplete.appendTo(args.element);
}
};
provide('grid', [ForeignKey, Edit, Toolbar]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
<template>
<div id="app">
<ejs-grid :dataSource='data' :toolbar="toolbar" :editSettings="editSettings" height="250">
<e-columns>
<e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right' isPrimaryKey="true" :validationRules='orderIDRules'></e-column>
<e-column field="EmployeeID" headerText="Employee Name" foreignKeyValue="FirstName" foreignKeyField="EmployeeID" :dataSource="employeeData" :edit='edit' width="120"></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130></e-column>
</e-columns>
</ejs-grid>
</div>
</template>
<script>
import { provide } from "vue";
import { createElement } from '@syncfusion/ej2-base';
import { GridComponent, ColumnsDirective, ColumnDirective, Toolbar, Edit, ForeignKey } from '@syncfusion/ej2-vue-grids';
import { DataManager, UrlAdaptor, Query } from '@syncfusion/ej2-data';
import { AutoComplete } from '@syncfusion/ej2-dropdowns';
var autoComplete;
export default {
name: "App",
components: {
'ejs-grid': GridComponent,
'e-columns': ColumnsDirective,
'e-column': ColumnDirective
},
data() {
return {
data: new DataManager({
url: 'https://localhost:****/api/Grid',
insertUrl: 'https://localhost:****/api/Grid/Insert',
updateUrl: 'https://localhost:****/api/Grid/Update',
removeUrl: 'https://localhost:****/api/Grid/Remove',
adaptor: new UrlAdaptor(),
}),
employeeData: new DataManager({
url: "https://localhost:****/api/Grid/employees",
adaptor: new UrlAdaptor(),
crossDomain: true
}),
orderIDRules : { required: true, number: true },
toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel'],
editSettings: { allowAdding: true, allowDeleting: true, allowEditing: true },
edit: {
create: () => {
return createElement('input');
},
read: () => {
return autoComplete.itemData?.employeeID;
},
destroy: () => {
autoComplete.destroy();
},
write: (args) => {
let selectedValue = args.foreignKeyData?.length > 0 ? args.foreignKeyData[0]['firstName'] : '';
autoComplete = new AutoComplete({
dataSource: this.employeeData,
fields: { value: 'firstName' },
value: selectedValue
});
autoComplete.appendTo(args.element);
}
},
};
},
provide: {
grid: [Toolbar, Edit, ForeignKey]
}
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-calendars/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind.css";
@import "../node_modules/@syncfusion/ej2-vue-grids/styles/tailwind.css";
</style>
Step 5: On the server side, create a controller named GridController.cs under the Controllers folder to handle API requests:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Syncfusion.EJ2.Base;
using EditTemplate.Server.Models;
namespace EditTemplate.Server.Controllers
{
[ApiController]
public class GridController : Controller
{
[HttpGet]
[Route("employees")]
public ActionResult<List<Employee>> GetEmployees()
{
return Employee.GetAllEmployees();
}
[HttpPost]
[Route("api/[controller]")]
public object Post()
{
// Retrieve data from the data source (e.g., database).
IQueryable<OrdersDetails> DataSource = GetOrderData().AsQueryable();
// Get the total records count.
int totalRecordsCount = DataSource.Count();
// Return data based on the request.
return new { result = DataSource, count = totalRecordsCount };
}
[HttpPost]
[Route("api/[controller]/employees")]
public ActionResult<List<Employee>> employees()
{
return Employee.GetAllEmployees();
}
[HttpGet]
[Route("api/[controller]")]
public List<OrdersDetails> GetOrderData()
{
var data = OrdersDetails.GetAllRecords().ToList();
return data;
}
/// <summary>
/// Inserts a new data item into the data collection.
/// </summary>
/// <param name="addRecord">The order to be inserted.</param>
/// <returns>It returns the newly inserted record detail.</returns>
[HttpPost]
[Route("api/[controller]/Insert")]
public ActionResult Insert([FromBody] CRUDModel<OrdersDetails> newRecord)
{
if (newRecord.value != null)
{
OrdersDetails.GetAllRecords().Insert(0, newRecord.value);
}
return Json(newRecord.value);
}
/// <summary>
/// Updates an existing order.
/// </summary>
/// <param name="updateRecord">The updated order details.</param>
/// <returns>It returns the updated order details.</returns>
[HttpPost]
[Route("api/[controller]/Update")]
public object Update([FromBody] CRUDModel<OrdersDetails> updatedRecord)
{
var updatedOrder = updatedRecord.value;
if (updatedOrder != null)
{
var data = OrdersDetails.GetAllRecords().FirstOrDefault(or => or.OrderID == updatedOrder.OrderID);
if (data != null)
{
// Update the existing record.
data.OrderID = updatedOrder.OrderID;
data.EmployeeID = updatedOrder.EmployeeID;
data.Freight = updatedOrder.Freight;
data.ShipCity = updatedOrder.ShipCity;
// Update other properties similarly.
}
}
return updatedRecord;
}
/// <summary>
/// Deletes an order.
/// </summary>
/// <param name="deletedRecord">It contains the specific record detail which is need to be removed.</param>
/// <returns>It returns the deleted record detail.</returns>
[HttpPost]
[Route("api/[controller]/Remove")]
public object Remove([FromBody] CRUDModel<OrdersDetails> deletedRecord)
{
int orderId = int.Parse(deletedRecord.key.ToString()); // Get key value from the deletedRecord.
var data = OrdersDetails.GetAllRecords().FirstOrDefault(orderData => orderData.OrderID == orderId);
if (data != null)
{
// Remove the record from the data collection.
OrdersDetails.GetAllRecords().Remove(data);
}
return deletedRecord;
}
public class CRUDModel<T> where T : class
{
public string? action { get; set; }
public string? keyColumn { get; set; }
public object? key { get; set; }
public T? value { get; set; }
public List<T>? added { get; set; }
public List<T>? changed { get; set; }
public List<T>? deleted { get; set; }
public IDictionary<string, object>? @params { get; set; }
}
}
}
Step 6: Create a model class named OrdersDetails.cs under the Models folder in the server-side project to represent the order data and employee data:
namespace EditTemplate.Server.Models
{
public class OrdersDetails
{
private static List<OrdersDetails> order = new List<OrdersDetails>();
public OrdersDetails() { }
public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified,
DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry,
DateTime ShippedDate, string ShipAddress)
{
this.OrderID = OrderID;
this.CustomerID = CustomerId;
this.EmployeeID = EmployeeId;
this.Freight = Freight;
this.ShipCity = ShipCity;
this.Verified = Verified;
this.OrderDate = OrderDate;
this.ShipName = ShipName;
this.ShipCountry = ShipCountry;
this.ShippedDate = ShippedDate;
this.ShipAddress = ShipAddress;
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count == 0)
{
int code = 10000;
List<Employee> employees = Employee.GetAllEmployees();
int employeeCount = employees.Count;
for (int i = 1; i < 10; i++)
{
order.Add(new OrdersDetails(code++, "ALFKI", employees[(code + 0) % employeeCount].EmployeeID, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
order.Add(new OrdersDetails(code++, "ANATR", employees[(code + 1) % employeeCount].EmployeeID, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123"));
order.Add(new OrdersDetails(code++, "ANTON", employees[(code + 2) % employeeCount].EmployeeID, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo"));
order.Add(new OrdersDetails(code++, "BLONP", employees[(code + 3) % employeeCount].EmployeeID, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7"));
order.Add(new OrdersDetails(code++, "BOLID", employees[(code + 4) % employeeCount].EmployeeID, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S."));
}
}
return order;
}
public int? OrderID { get; set; }
public string? CustomerID { get; set; }
public int? EmployeeID { get; set; }
public double? Freight { get; set; }
public string? ShipCity { get; set; }
public bool? Verified { get; set; }
public DateTime OrderDate { get; set; }
public string? ShipName { get; set; }
public string? ShipCountry { get; set; }
public DateTime ShippedDate { get; set; }
public string? ShipAddress { get; set; }
}
public class Employee
{
public int EmployeeID { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Department { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public static List<Employee> GetAllEmployees()
{
return new List<Employee>
{
new Employee { EmployeeID = 1, FirstName = "John", LastName = "Doe", Department = "Sales", Email = "john.doe@example.com", PhoneNumber = "123-456-7890" },
new Employee { EmployeeID = 2, FirstName = "David", LastName = "Smith", Department = "Marketing", Email = "david.smith@example.com", PhoneNumber = "987-654-3210" },
new Employee { EmployeeID = 3, FirstName = "Maria", LastName = "Gonzalez", Department = "HR", Email = "maria.gonzalez@example.com", PhoneNumber = "456-789-0123" },
new Employee { EmployeeID = 4, FirstName = "Sophia", LastName = "Brown", Department = "Finance", Email = "sophia.brown@example.com", PhoneNumber = "321-654-0987" },
new Employee { EmployeeID = 5, FirstName = "James", LastName = "Wilson", Department = "IT", Email = "james.wilson@example.com", PhoneNumber = "654-321-7654" },
new Employee { EmployeeID = 6, FirstName = "Emma", LastName = "Taylor", Department = "Operations", Email = "emma.taylor@example.com", PhoneNumber = "213-546-8790" },
new Employee { EmployeeID = 7, FirstName = "Daniel", LastName = "Anderson", Department = "Logistics", Email = "daniel.anderson@example.com", PhoneNumber = "789-654-3210" },
new Employee { EmployeeID = 8, FirstName = "Olivia", LastName = "Thomas", Department = "Procurement", Email = "olivia.thomas@example.com", PhoneNumber = "567-890-1234" },
new Employee { EmployeeID = 9, FirstName = "Michael", LastName = "Harris", Department = "R&D", Email = "michael.harris@example.com", PhoneNumber = "890-123-4567" },
new Employee { EmployeeID = 10, FirstName = "Lucas", LastName = "Martin", Department = "Customer Service", Email = "lucas.martin@example.com", PhoneNumber = "345-678-9012" },
new Employee { EmployeeID = 11, FirstName = "Elijah", LastName = "Clark", Department = "Support", Email = "elijah.clark@example.com", PhoneNumber = "741-852-9630" },
new Employee { EmployeeID = 12, FirstName = "Isabella", LastName = "Hall", Department = "Legal", Email = "isabella.hall@example.com", PhoneNumber = "963-852-7410" },
new Employee { EmployeeID = 13, FirstName = "Ethan", LastName = "Young", Department = "Administration", Email = "ethan.young@example.com", PhoneNumber = "258-963-1470" },
new Employee { EmployeeID = 14, FirstName = "Charlotte", LastName = "Scott", Department = "Design", Email = "charlotte.scott@example.com", PhoneNumber = "147-258-3690" },
new Employee { EmployeeID = 15, FirstName = "Alexander", LastName = "Allen", Department = "Engineering", Email = "alexander.allen@example.com", PhoneNumber = "369-147-2580" }
};
}
}
}
Step 7: In the Program.cs file, add the following code:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors();
app.UseDefaultFiles();
app.UseStaticFiles();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.MapFallbackToFile("/index.html");
app.Run();