How can I help you?
Templates in React Query Builder component
2 Mar 202624 minutes to read
Templates enable you to define customized headers and custom user interface elements for column values and filtering interactions.
Header Template
Customize the header section to create personalized user interfaces for managing rules and groups, including custom AND/OR and NOT condition controls. Implement header templates by creating a React component and assigning it when the actionBegin event fires with requestType as “header-template-create”.
The following example demonstrates a custom header using dropdown, split button, and button components:
import { QueryBuilderComponent, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-querybuilder';
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { HeaderTemplate } from './template';
function App() {
let qryBldrObj;
let importRules = {
'condition': 'and', 'not': true,
'rules': [{
'field': 'Age',
'label': 'Age',
'operator': 'equal',
'type': 'number',
'value': 30
},
{
'label': 'LastName',
'field': 'LastName',
'type': 'string',
'operator': 'equal',
'value': 'vinit'
},
{
'condition': 'or',
'rules': [{
'label': 'Age',
'field': 'Age',
'type': 'number',
'operator': 'equal',
'value': 34
}]
}
]
};
function headerTemplate(props) {
return (<HeaderTemplate {...props}/>);
}
return (<div>
<QueryBuilderComponent width='100%' rule={importRules} headerTemplate={headerTemplate} id='querybuilder' enableNotCondition="true">
<ColumnsDirective>
<ColumnDirective field="EmployeeID" label="Employee ID" type="number"/>
<ColumnDirective field="LastName" label="Last Name" type="string"/>
<ColumnDirective field="FirstName" label="First Name" type="string"/>
<ColumnDirective field="Age" label="Age" type="number"/>
<ColumnDirective field="City" label="City" type="string"/>
<ColumnDirective field="Country" label="Country" type="string"/>
</ColumnsDirective>
</QueryBuilderComponent>
</div>);
}
export default App;
ReactDom.render(<App />, document.getElementById('querybuilder-component'));import { QueryBuilderComponent, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-querybuilder';
import { RuleModel } from '@syncfusion/ej2-querybuider';
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { HeaderTemplate } from './template';
function App() {
let qryBldrObj: QueryBuilderComponent;
let importRules: RuleModel = {
'condition': 'and', 'not': true,
'rules': [{
'field': 'Age',
'label': 'Age',
'operator': 'equal',
'type': 'number',
'value': 30
},
{
'label': 'LastName',
'field': 'LastName',
'type': 'string',
'operator': 'equal',
'value': 'vinit'
},
{
'condition': 'or',
'rules': [{
'label': 'Age',
'field': 'Age',
'type': 'number',
'operator': 'equal',
'value': 34
}]
}
]
};
function headerTemplate(props) {
return (<HeaderTemplate {...props}/>);
}
return (<div>
<QueryBuilderComponent width='100%' rule={importRules} headerTemplate= {headerTemplate} id='querybuilder' enableNotCondition ="true" >
<ColumnsDirective>
<ColumnDirective field="EmployeeID" label="Employee ID" type="number"/>
<ColumnDirective field="LastName" label="Last Name" type="string"/>
<ColumnDirective field="FirstName" label="First Name" type="string"/>
<ColumnDirective field="Age" label="Age" type="number"/>
<ColumnDirective field="City" label="City" type="string"/>
<ColumnDirective field="Country" label="Country" type="string"/>
</ColumnsDirective>
</QueryBuilderComponent>
</div>);
}
export default App;
ReactDom.render(<App />,document.getElementById('querybuilder-component'));import * as React from 'react';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { getComponent, closest } from '@syncfusion/ej2-base';
import { CheckBoxComponent, ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { DropDownButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
export function HeaderTemplate(props) {
let ds = [{ 'key': 'AND', 'value': 'and' }, { 'key': 'OR', 'value': 'or' }];
let qryBldrObj;
let fields = { text: 'key', value: 'value' };
let ddbitems = [
{
text: 'AddGroup',
iconCss: 'e-icons e-add-icon e-addgroup'
},
{
text: 'AddCondition',
iconCss: 'e-icons e-add-icon e-addrule'
}
];
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder');
function onChange(args) {
qryBldrObj.notifyChange(args.checked, args.event.target, 'not');
}
function conditionChange(args) {
qryBldrObj.notifyChange(args.value, args.element, 'condition');
}
function onSelect(event) {
let addbtn = closest(event.element, '.e-dropdown-popup');
let ddbId = addbtn.id;
let ddb = ddbId.split('_');
if (event.item.text === 'AddGroup') {
qryBldrObj.addGroups([{ condition: 'or', 'rules': [{}], not: false }], ddb[1]);
}
else if (event.item.text === 'AddCondition') {
qryBldrObj.addRules([{}], ddb[1]);
}
}
function onClick(args) {
qryBldrObj.deleteGroup(closest(args.target.offsetParent, '.e-group-container'));
}
const args = state;
return (<div className="e-groupheader">
{(() => {
if (args.notCondition !== undefined) {
return (<button className="e-cb-wrapper">
<CheckBoxComponent id={args.ruleID + "_notOption"} label="not" checked={args.notCondition} change={onChange}/>
</button>);
}
})()}
<DropDownListComponent id={args.ruleID + "_cndtn"} cssClass='e-custom-group-btn' dataSource={ds} fields={fields} value={args.condition} change={conditionChange}/>
<DropDownButtonComponent id={args.ruleID + "_addbtn"} items={ddbitems} cssClass="e-round e-small e-caret-hide e-addrulegroup e-add-btn" iconCss="e-icons e-add-icon" select={onSelect}></DropDownButtonComponent>
{(() => {
if (args.ruleID !== "querybuilder_group0") {
return (<ButtonComponent id={args.ruleID + "_dltbtn"} cssClass='e-btn e-delete-btn e-lib e-small e-round e-icon-btn' iconCss="e-btn-icon e-icons e-delete-icon" onClick={onClick}></ButtonComponent>);
}
})()}
</div>);
}import * as React from 'react';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { getComponent, closest } from '@syncfusion/ej2-base';
import { CheckBoxComponent, ButtonComponent} from '@syncfusion/ej2-react-buttons';
import { DropDownButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
import { QueryBuilderComponent } from '@syncfusion/ej2-react-querybuider';
import { QueryBuilder, ActionEventArgs, RuleModel } from '@syncfusion/ej2-querybuider';
import { ItemModel, MenuEventArgs } from '@syncfusion/ej2-splitbuttons';
export function HeaderTemplate(props) {
let ds: { [key: string]: Object }[] = [{'key': 'AND', 'value': 'and'},{'key': 'OR', 'value': 'or'}];
let qryBldrObj: QueryBuilderComponent;
let fields: object = { text: 'key', value: 'value'};
let ddbitems: ItemModel[] = [
{
text: 'AddGroup',
iconCss: 'e-icons e-add-icon e-addgroup'
},
{
text: 'AddCondition',
iconCss: 'e-icons e-add-icon e-addrule'
}];
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder') as QueryBuilder;
function onChange(args: any): void{
qryBldrObj.notifyChange(args.checked, args.event.target, 'not');
}
function conditionChange(args: any): void{
qryBldrObj.notifyChange(args.value, args.element, 'condition');
}
function onSelect(event: MenuEventArgs): void{
let addbtn: Element= closest(event.element,'.e-dropdown-popup');
let ddbId: string = addbtn.id; let ddb: string[] = ddbId.split('_');
if (event.item.text === 'AddGroup') {
qryBldrObj.addGroups([{condition: 'or', 'rules': [{}], not: false}], ddb[1]);
} else if (event.item.text === 'AddCondition') {
qryBldrObj.addRules([{}], ddb[1]);
}
}
function onClick(args: any): void{
qryBldrObj.deleteGroup(closest(args.target.offsetParent, '.e-group-container'));
}
const args: ActionEventArgs = state;
return (<div className = "e-groupheader">
{(()=> {
if(args.notCondition !== undefined){
return( <button className = "e-cb-wrapper">
<CheckBoxComponent id = {args.ruleID + "_notOption"} label="not" checked={args.notCondition} change={onChange}/>
</button>);
}
})()}
<DropDownListComponent id = {args.ruleID + "_cndtn"} cssClass = 'e-custom-group-btn' dataSource={ds} fields={fields} value={args.condition} change={conditionChange}/>
<DropDownButtonComponent id = {args.ruleID + "_addbtn"} items={ddbitems} cssClass= "e-round e-small e-caret-hide e-addrulegroup e-add-btn" iconCss="e-icons e-add-icon" select={onSelect}></DropDownButtonComponent>
{(()=> {
if (args.ruleID !== "querybuilder_group0") {
return(<ButtonComponent id = {args.ruleID + "_dltbtn"} cssClass = 'e-btn e-delete-btn e-lib e-small e-round e-icon-btn' iconCss="e-btn-icon e-icons e-delete-icon" onClick={onClick} ></ButtonComponent>)
}
})()}
</div>
);
}Column Template
Replace the default input widgets with custom components for specific columns. Implement templates by defining the following functions:
-
create: Instantiate the custom component. -
write: Attach event handlers to the custom component. -
destroy: Clean up and remove the custom component.
The following example replaces the PaymentMode column input with a custom dropdown component:
import { getComponent } from '@syncfusion/ej2-base';
import { DropDownList, MultiSelect } from '@syncfusion/ej2-react-dropdowns';
import { QueryBuilderComponent } from '@syncfusion/ej2-react-querybuilder';
import * as React from 'react';
import * as ReactDom from 'react-dom';
// @ts-ignore
import { expenseData } from './datasource';
function App() {
let qryBldrObj;
let elem;
let dropDownObj;
let multiSelectObj;
let inOperators = ['in', 'notin'];
let filter = [
{
field: 'PaymentMode', label: 'Payment Mode', operators: [
{ key: 'Equal', value: 'equal' },
{ key: 'Not Equal', value: 'notequal' },
{ key: 'In', value: 'in' },
{ key: 'Not In', value: 'notin' }
], template: {
create: () => {
elem = document.createElement('input');
elem.setAttribute('type', 'text');
return elem;
},
destroy: (args) => {
multiSelectObj = getComponent(document.getElementById(args.elementId), 'multiselect');
if (multiSelectObj) {
multiSelectObj.destroy();
}
dropDownObj = getComponent(document.getElementById(args.elementId), 'dropdownlist');
if (dropDownObj) {
dropDownObj.destroy();
}
},
write: (args) => {
const ds = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking', 'Wallet'];
if (inOperators.indexOf(args.operator) > -1) {
multiSelectObj = new MultiSelect({
change: (e) => {
qryBldrObj.notifyChange(e.value, e.element);
},
dataSource: ds,
mode: 'CheckBox',
placeholder: 'Select Transaction',
value: args.values
});
multiSelectObj.appendTo('#' + args.elements.id);
}
else {
dropDownObj = new DropDownList({
change: (e) => {
qryBldrObj.notifyChange(e.itemData.value, e.element);
},
dataSource: ds,
value: args.values ? args.values : ds[0]
});
dropDownObj.appendTo('#' + args.elements.id);
}
}
}, type: 'string'
},
{ field: 'Description', label: 'Description', type: 'string' },
{ field: 'Date', label: 'Date', type: 'date' }
];
let importRules = {
'condition': 'or',
'rules': [{
'field': 'PaymentMode',
'label': 'PaymentMode',
'operator': 'equal',
'type': 'string',
'value': 'Cash'
}]
};
return (<QueryBuilderComponent dataSource={expenseData} columns={filter} width='100%' rule={importRules} ref={(scope) => { qryBldrObj = scope; }}/>);
}
export default App;
ReactDom.render(<App />, document.getElementById('querybuilder'));import { getComponent } from '@syncfusion/ej2-base';
import { ChangeEventArgs, DropDownList, MultiSelect, MultiSelectChangeEventArgs } from '@syncfusion/ej2-react-dropdowns';
import { ColumnsModel, QueryBuilderComponent, RuleModel } from '@syncfusion/ej2-react-querybuilder';
import * as React from 'react';
import * as ReactDom from 'react-dom';
// @ts-ignore
import { expenseData } from './datasource';
function App() {
let qryBldrObj: QueryBuilderComponent;
let elem: HTMLElement;
let dropDownObj: DropDownList;
let multiSelectObj: MultiSelect;
let inOperators: string [] = ['in', 'notin'];
let filter: ColumnsModel[] = [
{
field: 'PaymentMode', label: 'Payment Mode', operators: [
{ key: 'Equal', value: 'equal' },
{ key: 'Not Equal', value: 'notequal' },
{ key: 'In', value: 'in' },
{ key: 'Not In', value: 'notin' }
], template: {
create: () => {
elem = document.createElement('input');
elem.setAttribute('type', 'text');
return elem;
},
destroy: (args: { elementId: string }) => {
multiSelectObj = getComponent(document.getElementById(args.elementId) as HTMLElement, 'multiselect') as MultiSelect;
if (multiSelectObj) {
multiSelectObj.destroy();
}
dropDownObj = getComponent(document.getElementById(args.elementId) as HTMLElement, 'dropdownlist') as DropDownList;
if (dropDownObj) {
dropDownObj.destroy();
}
},
write: (args: { elements: Element, values: string[] | string, operator: string }) => {
const ds = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking', 'Wallet'];
if (inOperators.indexOf(args.operator) > -1) {
multiSelectObj = new MultiSelect({
change: (e: MultiSelectChangeEventArgs) => {
qryBldrObj.notifyChange(e.value as string[], e.element);
},
dataSource: ds,
mode: 'CheckBox',
placeholder: 'Select Transaction',
value: args.values as string []
});
multiSelectObj.appendTo('#' + args.elements.id);
} else {
dropDownObj = new DropDownList({
change: (e: ChangeEventArgs) => {
qryBldrObj.notifyChange(e.itemData.value as string, e.element);
},
dataSource: ds,
value: args.values ? args.values as string : ds[0]
});
dropDownObj.appendTo('#' + args.elements.id);
}
}
}, type: 'string'
},
{ field: 'Description', label: 'Description', type: 'string' },
{ field: 'Date', label: 'Date', type: 'date' }
];
let importRules: RuleModel = {
'condition': 'or',
'rules': [{
'field': 'PaymentMode',
'label': 'PaymentMode',
'operator': 'equal',
'type': 'string',
'value': 'Cash'
}]
};
return (
<QueryBuilderComponent dataSource={expenseData} columns={filter} width='100%' rule={importRules} ref={(scope) => { qryBldrObj = scope as QueryBuilderComponent; }} />
);
}
export default App;
ReactDom.render(<App />,document.getElementById('querybuilder'));Using Template
Create customized input widgets by implementing templates as React components. This approach provides maximum flexibility for rendering specialized controls based on your application requirements.
import { QueryBuilderComponent, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-querybuilder';
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { PaymentTemplate } from './payment-temp';
import { TransactionTemplate } from './transaction-temp';
function App() {
let qryBldrObj;
let importRules = {
'condition': 'and',
'rules': [{
'label': 'Transaction Type',
'field': 'TransactionType',
'type': 'string',
'operator': 'equal',
'value': 'Expense'
},
{
'label': 'Payment Mode',
'field': 'PaymentMode',
'type': 'string',
'operator': 'equal',
'value': 'Cash'
}]
};
function paymentTemplate(props) {
return (<PaymentTemplate {...props}/>);
}
function transactionTemplate(props) {
return (<TransactionTemplate {...props}/>);
}
return (<div>
<QueryBuilderComponent width='100%' rule={importRules} id='querybuilder'>
<ColumnsDirective>
<ColumnDirective field="Category" label="Category" type="string"/>
<ColumnDirective field="PaymentMode" label="PaymentMode" type="string" template={paymentTemplate}/>
<ColumnDirective field="TransactionType" label="TransactionType" type="string" template={transactionTemplate}/>
<ColumnDirective field="Description" label="Description" type="string"/>
<ColumnDirective field="Date" label="Date" type="string"/>
<ColumnDirective field="Amount" label="Amount" type="string"/>
</ColumnsDirective>
</QueryBuilderComponent>
</div>);
}
export default App;
ReactDom.render(<App />, document.getElementById('querybuilder-component'));import { QueryBuilderComponent, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-querybuilder';
import { RuleModel } from '@syncfusion/ej2-querybuider';
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { PaymentTemplate } from './payment-temp';
import { TransactionTemplate } from './transaction-temp';
function App() {
let qryBldrObj: QueryBuilderComponent;
let importRules: RuleModel = {
'condition': 'and',
'rules': [{
'label': 'Transaction Type',
'field': 'TransactionType',
'type': 'string',
'operator': 'equal',
'value': 'Expense'
},
{
'label': 'Payment Mode',
'field': 'PaymentMode',
'type': 'string',
'operator': 'equal',
'value': 'Cash'
}]
};
function paymentTemplate(props) {
return (<PaymentTemplate {...props}/>);
}
function transactionTemplate(props) {
return (<TransactionTemplate {...props}/>);
}
return (<div>
<QueryBuilderComponent width='100%' rule={importRules} id='querybuilder' >
<ColumnsDirective>
<ColumnDirective field="Category" label="Category" type="string"/>
<ColumnDirective field="PaymentMode" label="PaymentMode" type="string" template = {paymentTemplate}/>
<ColumnDirective field="TransactionType" label="TransactionType" type="string" template = {transactionTemplate}/>
<ColumnDirective field="Description" label="Description" type="string"/>
<ColumnDirective field="Date" label="Date" type="string"/>
<ColumnDirective field="Amount" label="Amount" type="string"/>
</ColumnsDirective>
</QueryBuilderComponent>
</div>);
}
export default App;
ReactDom.render(<App />,document.getElementById('querybuilder-component'));import * as React from 'react';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { getComponent } from '@syncfusion/ej2-base';
export function PaymentTemplate(props) {
let ds = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking'];
let qryBldrObj;
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder');
const args = state;
function paymentChange(event) {
const args = state;
let elem = document.getElementById(args.ruleID).querySelector('.e-rule-value');
qryBldrObj.notifyChange(event.value, elem, 'value');
}
return (<div>
<DropDownListComponent dataSource={ds} value={args.rule.value} change={paymentChange}/>
</div>);
}import * as React from 'react';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { getComponent, closest } from '@syncfusion/ej2-base';
import { QueryBuilderComponent } from '@syncfusion/ej2-react-querybuider';
import { QueryBuilder, ActionEventArgs, RuleModel } from '@syncfusion/ej2-querybuider';
export function PaymentTemplate(props) {
let ds: string[] = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking'];
let qryBldrObj: QueryBuilderComponent;
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder') as QueryBuilder;
const args: ActionEventArgs = state;
function paymentChange(event: any): void{
const args: ActionEventArgs = state;
let elem: HTMLElement = document.getElementById(args.ruleID).querySelector('.e-rule-value');
qryBldrObj.notifyChange(event.value as string, elem, 'value');
}
return (<div >
<DropDownListComponent dataSource={ds} value={args.rule.value} change={paymentChange}/>
</div>
);
}import * as React from 'react';
import { getComponent } from '@syncfusion/ej2-base';
import { CheckBoxComponent } from '@syncfusion/ej2-react-buttons';
export function TransactionTemplate(props) {
let qryBldrObj;
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder');
const args = state;
function transactionChange(event) {
const args = state;
let elem = document.getElementById(args.ruleID).querySelector('.e-rule-value');
qryBldrObj.notifyChange(event.checked === true ? 'Expense' : 'Income', elem, 'value');
}
return (<div>
<CheckBoxComponent label="Is Expense" checked={args.rule.value} change={transactionChange}/>
</div>);
}import * as React from 'react';
import { getComponent, closest } from '@syncfusion/ej2-base';
import { CheckBoxComponent, ButtonComponent} from '@syncfusion/ej2-react-buttons';
import { QueryBuilderComponent } from '@syncfusion/ej2-react-querybuider';
import { QueryBuilder, ActionEventArgs, RuleModel } from '@syncfusion/ej2-querybuider';
export function TransactionTemplate(props) {
let qryBldrObj: QueryBuilderComponent;
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder') as QueryBuilder;
const args: ActionEventArgs = state;
function transactionChange(event: any): void{
const args: ActionEventArgs = state;
let elem: HTMLElement = document.getElementById(args.ruleID).querySelector('.e-rule-value');
qryBldrObj.notifyChange(event.checked === true ? 'Expense' : 'Income', elem, 'value');
}
return (<div>
<CheckBoxComponent label="Is Expense" checked={args.rule.value} change={transactionChange}/>
</div>
);
}Rule Template
Rule Template allows to define your own user interface for columns. To implement ruleTemplate, you can create the user interface as React component and assign the values through actionBegin event.
In the following sample, dropdown and slider are used as the custom component and applied greaterthanorequal operator to Age column.
import { QueryBuilderComponent, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-querybuilder';
import * as React from 'react';
import * as ReactDom from 'react-dom';
// @ts-ignore
import { employeeData } from './datasource';
import { AgeTemplate } from './template';
function App() {
let qryBldrObj;
let elem;
let importRules = {
'condition': 'or',
'rules': [{
'field': 'Age',
'label': 'Age',
'operator': 'greaterthanorequal',
'type': 'number',
'value': 30
}]
};
function ageTemplate(props) {
return (<AgeTemplate {...props}/>);
}
function actionBegin(args) {
let ruleID = args.ruleID;
args.rule.operator = 'greaterthanorequal';
if (args.requestType === 'template-initialize') {
if (args.rule.value === '') {
args.rule.value = 30;
}
}
}
return (<QueryBuilderComponent dataSource={employeeData} width='100%' rule={importRules} ref={(scope) => { qryBldrObj = scope; }} actionBegin={actionBegin} id='querybuilder'>
<ColumnsDirective>
<ColumnDirective field="EmployeeID" label="Employee ID" type="number"/>
<ColumnDirective field="LastName" label="Last Name" type="string"/>
<ColumnDirective field="FirstName" label="First Name" type="string"/>
<ColumnDirective field="Age" label="Age" type="number" ruleTemplate={ageTemplate}/>
<ColumnDirective field="City" label="City" type="string"/>
<ColumnDirective field="Country" label="Country" type="string"/>
</ColumnsDirective>
</QueryBuilderComponent>);
}
export default App;
ReactDom.render(<App />, document.getElementById('querybuilder-component'));import { getComponent, setValue } from '@syncfusion/ej2-base';
import { ChangeEventArgs, DropDownList } from '@syncfusion/ej2-react-dropdowns';
import { QueryBuilderComponent, ColumnsDirective, ColumnDirective, RuleModel, ActionEventArgs } from '@syncfusion/ej2-react-querybuilder';
import * as React from 'react';
import * as ReactDom from 'react-dom';
// @ts-ignore
import { employeeData } from './datasource';
import { AgeTemplate } from './template';
function App() {
let qryBldrObj: QueryBuilderComponent;
let elem: HTMLElement;
let importRules: RuleModel = {
'condition': 'or',
'rules': [{
'field': 'Age',
'label': 'Age',
'operator': 'greaterthanorequal',
'type': 'number',
'value': 30
}]
};
function ageTemplate(props): any {
return (<AgeTemplate {...props} />);
}
function actionBegin(args: ActionEventArgs): void {
let ruleID = args.ruleID;
args.rule.operator = 'greaterthanorequal';
if (args.requestType === 'template-initialize') {
if (args.rule.value === '') {
args.rule.value = 30;
}
}
}
return (
<QueryBuilderComponent dataSource={employeeData} width='100%' rule={importRules} ref={(scope) => { qryBldrObj = scope as QueryBuilderComponent; }} actionBegin={actionBegin} id='querybuilder'>
<ColumnsDirective>
<ColumnDirective field="EmployeeID" label="Employee ID" type="number"/>
<ColumnDirective field="LastName" label="Last Name" type="string"/>
<ColumnDirective field="FirstName" label="First Name" type="string"/>
<ColumnDirective field="Age" label="Age" type="number" ruleTemplate={ageTemplate}/>
<ColumnDirective field="City" label="City" type="string"/>
<ColumnDirective field="Country" label="Country" type="string"/>
</ColumnsDirective>
</QueryBuilderComponent>
);
}
export default App;
ReactDom.render(<App />,document.getElementById('querybuilder-component'));import * as React from 'react';
import { SliderComponent } from '@syncfusion/ej2-react-inputs';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { getComponent, compile } from '@syncfusion/ej2-base';
import { DataManager, Query } from '@syncfusion/ej2-data';
import { employeeData } from './datasource';
export function AgeTemplate(props) {
let qryBldrObj;
let sliderObj;
let rangeTicks = { placement: 'Before', largeStep: 5, showSmallTicks: true };
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder');
function fieldChange(args) {
qryBldrObj.notifyChange(args.value, args.element, 'field');
}
function valueChange(args) {
let elem = sliderObj.element;
qryBldrObj.notifyChange(args.value, elem, 'value');
refreshTable(qryBldrObj.getRule(elem), elem.id.split('_valuekey0')[0]);
}
function sliderCreated() {
let elem = sliderObj.element;
refreshTable(qryBldrObj.getRule(elem), elem.id.split('_valuekey0')[0]);
}
function myFunction(ruleID) {
let element = document.getElementById(ruleID + '_section');
if (element.className.indexOf('e-hide') > -1) {
element.className = element.className.replace('e-hide', '');
document.getElementById(ruleID + '_option').textContent = 'Hide Details';
}
else {
element.className += ' e-hide';
document.getElementById(ruleID + '_option').textContent = 'View Details';
}
}
function refreshTable(rule, ruleID) {
let template = '<tr><td>${EmployeeID}</td><td>${FirstName}</td><td>${Age}</td></tr>';
let compiledFunction = compile(template);
let predicate = qryBldrObj.getPredicate({ condition: 'and', rules: [rule] });
let dataManagerQuery = new Query().select(['EmployeeID', 'FirstName', 'Age']).where(predicate);
let result = new DataManager(employeeData).executeLocal(dataManagerQuery);
let table = document.getElementById(ruleID + '_datatable');
if (result.length) {
table.style.display = 'block';
}
else {
table.style.display = 'none';
}
table.querySelector('tbody').innerHTML = '';
result.forEach((data) => {
table.querySelector('tbody').appendChild(compiledFunction(data)[0].querySelector('tr'));
});
}
const args = state;
return (<div className="e-rule e-rule-template">
<div className="e-rule-filter e-custom-filter">
<DropDownListComponent change={fieldChange} fields={args.fields} dataSource={args.columns} value={args.rule.field}/>
</div>
<div>
<div className="e-slider-value">
<SliderComponent ticks={rangeTicks} ref={(scope) => { sliderObj = scope; }} id={args.ruleID + '_valuekey0'} change={valueChange} created={sliderCreated} value={args.rule.value} min={30} max={50}/>
</div>
<div className="e-rule-btn">
<button id={args.ruleID + '_option'} onClick={myFunction.bind(this, args.ruleID)} className="e-primary e-btn e-small">
View Details
</button>
<button className="e-removerule e-rule-delete e-css e-btn e-small e-round">
<span className="e-btn-icon e-icons e-delete-icon"/>
</button>
</div>
</div>
<div id={args.ruleID + '_section'} className="e-rule-value-group e-hide">
<div>
<table id={args.ruleID + '_datatable'} className='e-rule-table e-hide'>
<thead>
<tr><th>EmployeeID</th><th>FirstName</th><th>Age</th></tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>);
}import * as React from 'react';
import { SliderComponent } from '@syncfusion/ej2-react-inputs';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { getComponent, compile } from '@syncfusion/ej2-base';
import { DataManager, Predicate, Query } from '@syncfusion/ej2-data';
import { QueryBuilderComponent } from '@syncfusion/ej2-react-querybuider';
import { QueryBuilder, ActionEventArgs, RuleModel } from '@syncfusion/ej2-querybuider';
import { employeeData } from './datasource';
export function AgeTemplate(props) {
let qryBldrObj: QueryBuilderComponent;
let sliderObj: SliderComponent;
let rangeTicks: object = { placement: 'Before', largeStep: 5, showSmallTicks: true };
let state = Object.assign({}, props);
qryBldrObj = getComponent(document.getElementById('querybuilder'), 'query-builder') as QueryBuilder;
function fieldChange(args: any): void {
qryBldrObj.notifyChange(args.value, args.element, 'field');
}
function valueChange(args: any): void {
let elem: Element = sliderObj.element;
qryBldrObj.notifyChange(args.value, elem, 'value');
refreshTable(qryBldrObj.getRule(elem), elem.id.split('_valuekey0')[0]);
}
function sliderCreated() {
let elem: Element = sliderObj.element;
refreshTable(qryBldrObj.getRule(elem), elem.id.split('_valuekey0')[0]);
}
function myFunction(ruleID: string): void {
let element: Element = document.getElementById(ruleID + '_section');
if (element.className.indexOf('e-hide') > -1) {
element.className = element.className.replace('e-hide', '');
document.getElementById(ruleID + '_option').textContent = 'Hide Details';
} else {
element.className += ' e-hide';
document.getElementById(ruleID + '_option').textContent = 'View Details';
}
}
function refreshTable(rule: RuleModel, ruleID: string): void {
let template: string = '<tr><td>${EmployeeID}</td><td>${FirstName}</td><td>${Age}</td></tr>';
let compiledFunction: any = compile(template);
let predicate: Predicate = qryBldrObj.getPredicate({condition: 'and', rules: [rule]});
let dataManagerQuery: Query = new Query().select(['EmployeeID', 'FirstName', 'Age']).where(predicate);
let result: object[] = new DataManager(employeeData).executeLocal(dataManagerQuery);
let table: HTMLElement = document.getElementById(ruleID + '_datatable') as HTMLElement;
if (result.length) {
table.style.display = 'block';
} else {
table.style.display = 'none';
}
table.querySelector('tbody').innerHTML = '';
result.forEach((data) => {
table.querySelector('tbody').appendChild(compiledFunction(data)[0].querySelector('tr'));
});
}
const args: ActionEventArgs = state;
return (
<div className="e-rule e-rule-template">
<div className="e-rule-filter e-custom-filter">
<DropDownListComponent change={fieldChange} fields={args.fields} dataSource={args.columns} value={args.rule.field}/>
</div>
<div>
<div className="e-slider-value">
<SliderComponent ticks={rangeTicks} ref={(scope) => { sliderObj = scope as SliderComponent; }} id={args.ruleID + '_valuekey0'} change={valueChange} created={sliderCreated} value={args.rule.value} min={30} max={50} />
</div>
<div className="e-rule-btn">
<button id={args.ruleID + '_option'} onClick={myFunction.bind(this, args.ruleID)} className="e-primary e-btn e-small">
View Details
</button>
<button className="e-removerule e-rule-delete e-css e-btn e-small e-round">
<span className="e-btn-icon e-icons e-delete-icon"/>
</button>
</div>
</div>
<div id={args.ruleID + '_section'} className="e-rule-value-group e-hide">
<div>
<table id={args.ruleID + '_datatable'} className='e-rule-table e-hide'>
<thead>
<tr><th>EmployeeID</th><th>FirstName</th><th>Age</th></tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
);
}