Templates in EJ2 TypeScript Query Builder UI

4 Sep 202624 minutes to read

Templates help define custom header and column UI for the Query Builder.

Header template

The header template allows creating a custom header UI for actions such as rule and group creation, and for customizing AND/OR and NOT condition options. To implement it, create the UI with x-template and assign values when requestType is header-template-create in the actionBegin event.

In the following sample, Dropdown, SplitButton, and Button are used as custom header components.

import { QueryBuilder, RuleModel, ColumnsModel, ActionEventArgs} from  '@syncfusion/ej2-querybuilder'
import { closest } from '@syncfusion/ej2-base';
import { DropDownButton, ItemModel, MenuEventArgs } from '@syncfusion/ej2-splitbuttons';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { CheckBox } from '@syncfusion/ej2-buttons';

let filter: ColumnsModel [] = [
    { field: 'EmployeeID', label: 'EmployeeID', type: 'number'},
    { field: 'FirstName', label: 'FirstName', type: 'string'},
    { field: 'LastName', label: 'LastName', type: 'string'},
    { field: 'Age', label: 'Age', type: 'number'},
    { field: 'City', label: 'City', type: 'string'},
    { field: 'Country', label: 'Country', type: 'string'},
];

let importRules: RuleModel = {
    'condition': 'and', 'not': true,
    'rules': [{
        'label': 'Age',
        'field': 'Age',
        'type': 'number',
        'operator': 'equal',
        'value': 34
    },
    {
        'label': 'LastName',
        'field': 'LastName',
        'type': 'string',
        'operator': 'equal',
        'value': 'vinit'
    },
    {
    'condition': 'or',
    'rules': [{
        'label': 'Age',
        'field': 'Age',
        'type': 'number',
        'operator': 'equal',
        'value': 34
    }]
}]
};

let queryBldrObj: QueryBuilder = new QueryBuilder({
    columns: filter,
    width: '100%',
    rule: importRules,
    headerTemplate: '#headerTemplate',
    actionBegin: actionBegin,
    enableNotCondition: true
});
queryBldrObj.appendTo('#querybuilder');

    function actionBegin(args: ActionEventArgs): void {
        if (args.requestType === 'header-template-create') {
            let checkBoxObj: CheckBox = new CheckBox({
                label: 'NOT',
                checked: args.notCondition,
                change: function(e:any){
                    queryBldrObj.notifyChange(e.checked,e.event.target, 'not')
                }
             });
            checkBoxObj.appendTo('#' + args.ruleID + '_notoption');
            let ds: { [key: string]: Object }[] = [{'key': 'AND', 'value': 'and'},{'key': 'OR', 'value': 'or'}];
            let btnObj: DropDownList= new DropDownList({
                dataSource: ds,
                fields: { text: 'key', value: 'value' },
                value: args.condition,
                cssClass: 'e-custom-group-btn e-active-toggle',
                change: (e: any) => {
                    queryBldrObj.notifyChange(e.value, e.element, 'condition');
                }
            });
            btnObj.appendTo('#' + args.ruleID + '_cndtnbtn');
            let ddbitems: ItemModel[] = [
                { text: 'AddGroup', iconCss: 'e-icons e-add-icon e-addgroup' },
                { text: 'AddCondition', iconCss: 'e-icons e-add-icon e-addrule' }
            ];
            let addbtn: DropDownButton = new DropDownButton({
                items: ddbitems,
                cssClass: 'e-round e-small e-caret-hide e-addrulegroup',
                iconCss: 'e-icons e-add-icon',
                select: function(event: MenuEventArgs) {
                    let addbtn: Element = closest(event.element,'.e-dropdown-popup');  let ddb: string[]= addbtn.id.split('_');
                    if (event.item.text === 'AddGroup') {
                        queryBldrObj.addGroups([{condition: 'and', 'rules': [{}], not: false}], ddb[1]);
                    } else if (event.item.text === 'AddCondition') {
                        queryBldrObj.addRules([{}], ddb[1]);
                    }
                }
            });
            addbtn.appendTo('#' + args.ruleID + '_addbtn');
            let deleteGroup: Element =  document.getElementById(args.ruleID).querySelector('.e-delete-btn');
            if (deleteGroup) {
                (deleteGroup as HTMLElement).onclick = function (e:any) {
                    queryBldrObj.deleteGroup(closest(e.target.offsetParent, '.e-group-container'));
                }
            }
        }
    }
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Query Builder</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-querybuilder/styles/material.css" rel="stylesheet" />
    <link href="styles.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    
</head>

<body>
    <div id='loader'>LOADING....</div>
    <div id='container'>
        <div id='querybuilder'></div>
    </div>
    <script id="headerTemplate" type="text/x-template">
        <div class = 'e-groupheader'>
            ${if(notCondition !== undefined)}
                <button class='e-cb-wrapper'>
                    <input type="checkbox" class= "e-not" id='${ruleID}_notoption' checked='${notCondition}'>
                </button>
            ${/if}
            <input type="text" class= "e-custom-group-btn"  id='${ruleID}_cndtnbtn'>
            <button id = '${ruleID}_addbtn' class = 'e-add-btn'></button>
            ${if(ruleID !== 'querybuilder_group0')}
                <button  id= 'dltbtn' class = "e-btn e-delete-btn e-lib e-small e-round e-icon-btn">
                    <span class = 'e-btn-icon e-icons e-delete-icon'></span>
                </button>
            ${/if}
        </div>
    </script>
    <style type="text/css">
    .e-query-builder .e-add-btn {
        margin-left: 10px;
        margin-right: 10px;
    }
    .e-query-builder .cndtnbtn.e-control.e-dropdownlist.e-lib.e-input {
        padding-left: 10px;
    }
    .e-query-builder span.e-custom-group-btn {
        max-width: 100px;
        border-radius: 5px  !important;
        border-width: 1px  !important; 
    }
    .e-query-builder .e-custom-group-btn.e-input-focus::before, .e-custom-group-btn.e-input-focus::after {
        background: transparent !important;
    }
    .e-query-builder .e-group-header .e-addrulegroup, .e-group-header .e-delete-btn {
        border: 1px solid grey !important;
    }
    .e-query-builder .e-group-header .e-addrulegroup:hover, .e-group-header .e-delete-btn:hover {
        border: 1px solid grey !important;
    }
    .e-query-builder .e-toggle{
        background: #317ab9;
        border-color: #317ab9;
        color: #fff;
    }
    .e-query-builder .e-cb-wrapper {
        margin-right: 5px;
        height: 32px;
        border-radius: 5px;
        border: 1px solid gray;
        background-color: white;
    }
    .e-query-builder .e-custom-group-btn{
        padding-left: 10px;
        height: 32px;
    }
    </style>
</body>
</html>

Column template

The column template allows defining custom input widgets for columns. To implement template, define the following functions:

  • create: Creates the custom component.
  • write: Wires events for the custom component.
  • destroy: Destroys the custom component.

In the following sample, dropdown is used as the custom component in the PaymentMode column.

import { QueryBuilder, ColumnsModel, RuleModel } from '@syncfusion/ej2-querybuilder';
import { getComponent } from '@syncfusion/ej2-base';
import { TextBox } from '@syncfusion/ej2-inputs';
import { DropDownList, MultiSelect, CheckBoxSelection } from '@syncfusion/ej2-dropdowns';

let expenseData: Object[]  = [{
    'Category': 'Food',
    'PaymentMode': 'Credit Card',
    'TransactionType': 'Expense',
    'Description': 'Boiled peanuts',
    'Amount': '7',
    'Date': '06/01/2017'
  }, {

    'Category': 'Food',
    'PaymentMode': 'Cash',
    'TransactionType': 'Expense',
    'Description': 'Peanuts in Coke',
    'Amount': '8',
    'Date': '06/04/2017'
  }, {
    'Category': 'Food',
    'PaymentMode': 'Cash',
    'TransactionType': 'Expense',
    'Description': 'Palmetto Cheese, Mint julep',
    'Amount': '11',
    'Date': '06/04/2017'
  }];

    let elem: HTMLElement;
    let inOperators: string [] = ['in', 'notin'];
    let columnData: ColumnsModel[] = [
        { field: 'Category', label: 'Category', type: 'string' },
        { field: 'TransactionType', label: 'Transaction Type', type: 'boolean' },
        {
            field: 'PaymentMode', label: 'Payment Mode', type: 'string', template: {
                create: () => {
                    elem = document.createElement('input');
                    elem.setAttribute('type', 'text');
                    return elem;
                },
                destroy: (args: { elementId: string }) => {
                    let multiSelect: MultiSelect = (getComponent(document.getElementById(args.elementId), 'multiselect') as MultiSelect);
                    if (multiSelect) {
                        multiSelect.destroy();
                    }
                    let dropdown: DropDownList = (getComponent(document.getElementById(args.elementId), 'dropdownlist') as DropDownList);
                    if (dropdown) {
                        dropdown.destroy();
                    }
                },
                write: (args: { elements: Element, values: string[] | string, operator: string }) => {
                    let ds: string[] = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking', 'Wallet'];
                    if (inOperators.indexOf(args.operator) > -1) {
                        let multiSelectObj: MultiSelect = new MultiSelect({
                            dataSource: ds,
                            value: args.values as string [],
                            mode: 'CheckBox',
                            placeholder: 'Select Transaction',
                            change: (e: any) => {
                                qryBldrObj.notifyChange(e.value, e.element);
                            }
                        });
                        multiSelectObj.appendTo('#' + args.elements.id);
                    } else {
                        let dropDownObj: DropDownList = new DropDownList({
                            dataSource: ds,
                            value: args.values as string,
                            change: (e: any) => {
                                qryBldrObj.notifyChange(e.itemData.value, e.element);
                            }
                        });
                        dropDownObj.appendTo('#' + args.elements.id);
                    }
                }
            },
            operators: [
                { value: 'equal', key: 'Equal' },
                { value: 'notequal', key: 'Not Equal' },
                { value: 'in', key: 'In' },
                { value: 'notin', key: 'Not In' }
            ],
        },
        { field: 'Description', label: 'Description', type: 'string' },
        { field: 'Date', label: 'Date', type: 'date' },
        { field: 'Amount', label: 'Amount', type: 'number' }
    ];

    let importRules: RuleModel = {
        'condition': 'and',
        'rules': [{
                'label': 'Payment Mode',
                'field': 'PaymentMode',
                'type': 'string',
                'operator': 'equal',
                'value': 'Cash'
            }
        ]
    };
    let qryBldrObj: QueryBuilder = new QueryBuilder({
        dataSource: expenseData,
        columns: columnData,
        width: '70%',
        rule: importRules
    });
    qryBldrObj.appendTo('#querybuilder');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Query Builder</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-querybuilder/styles/material.css" rel="stylesheet" />
    <link href="styles.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    
</head>

<body>
    <div id='loader'>LOADING....</div>
    <div id='container'>
        <div id='querybuilder'></div>
         <div id='property'> </div>
    </div>
</body>
</html>

Template configuration

To implement a custom template in the Query Builder, create the UI with x-template and assign values through the actionBegin event.

import { QueryBuilder, RuleModel, ColumnsModel, ActionEventArgs} from '@syncfusion/ej2-querybuilder';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { CheckBox } from '@syncfusion/ej2-buttons';

let filter: ColumnsModel [] = [
    { field:"Category" label:"Category" type:"string"},
    { field: 'PaymentMode', label: 'PaymentMode', type: 'string', operators: customOperators , template:"#paymentTemplate"},
    { field: 'TransactionType', label: 'TransactionType', type: 'string',  operators: customOperators, template:"#transactionTemplate"},
    { field: 'Description', label: 'Description', type: 'string' },
    { field: 'Date', label: 'Date', type: 'string'},
    { field: 'Amount', label: 'Amount', type: 'string'},
];

let customOperators: { [key: string]: Object }[] = [{value: 'equal', key: 'Equal'},
  {value: 'notequal', key: 'Not Equal'}];
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'
  }]
};

let valueObj: Slider;
let queryBldrObj: QueryBuilder = new QueryBuilder({
    columns: filter,
    rule: importRules,
    width: '100%',
    actionBegin: actionBegin
});
queryBldrObj.appendTo('#querybuilder');


function actionBegin(args: ActionEventArgs): void {
    let ruleID: string = args.ruleID
    if (args.requestType === 'value-template-create') {
        let checkBoxObj: CheckBox = new CheckBox({
            label: 'Is Expense',
            checked: args.rule.value === "Expense" ? true: false,
            change: function(e:any){
                let elem: HTMLElement = document.getElementById(ruleID).querySelector('.e-rule-value');qryBldrObj.notifyChange(e.checked === true ? 'Expense' : 'Income', elem, 'value');
            }
        });
        checkBoxObj.appendTo('#' + args.ruleID + '_checkbox');
        let ds: string[] = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking'];
        let btnObj: DropDownList= new DropDownList({
                dataSource: ds,
                fields: { text: 'key', value: 'value' },
                value: args.rule.value,
                change: (e: any) => {
                 let elem: HTMLElement = document.getElementById(ruleID).querySelector('.e-rule-value');qryBldrObj.notifyChange(e.value as string, elem, 'value');
                }
        });
        btnObj.appendTo('#' + args.ruleID + '_paymentlist');
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Query Builder</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-querybuilder/styles/material.css" rel="stylesheet" />
    <link href="styles.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    
</head>

<body>
    <div id='loader'>LOADING....</div>
    <div id='container'>
        <div id='querybuilder'></div>
    </div>
    <script id="paymentTemplate" type="text/x-template">
        <input type="text" class= "e-payment-list"  id='${ruleID}_paymentlist'>
    </script>
    <script id="transactionTemplate" type="text/x-template">
        <input type="checkbox" class= "e-checkbox"  id='${ruleID}_checkbox'>
    </script>
    
	<style type="text/css">
		
	</style>
</body>
</html>

Rule template

The rule template allows defining a custom UI for a column. To implement ruleTemplate, create the UI with x-template and assign values in the actionBegin event.

In the following sample, dropdown and slider are used as custom components in the Age column, and the greaterthanorequal operator is applied to this column.

import { QueryBuilder, RuleModel, ColumnsModel, ActionEventArgs} from '@syncfusion/ej2-querybuilder';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { Slider } from '@syncfusion/ej2-inputs';
import { employeeData } from './datasource.ts';
import { DataManager, Query } from '@syncfusion/ej2-data';
import { compile } from '@syncfusion/ej2-base';

let filter: ColumnsModel [] = [
    { field: 'EmployeeID', label: 'EmployeeID', type: 'number'},
    { field: 'FirstName', label: 'FirstName', type: 'string'},
    { field: 'LastName', label: 'LastName', type: 'string'},
    { field: 'Age', label: 'Age', type: 'number', ruleTemplate: '#ageTemplate'},
    { field: 'City', label: 'City', type: 'string'},
    { field: 'Country', label: 'Country', type: 'string'},
];

let importRules: RuleModel = {
    'condition': 'and',
    'rules': [{
        'label': 'Age',
        'field': 'Age',
        'type': 'number',
        'operator': 'greaterthanorequal',
        'value': 30
    }]
};

let fieldObj: DropDownList;
let valueObj: Slider;
let ruleID: string;

let queryBldrObj: QueryBuilder = new QueryBuilder({
    columns: filter,
    dataSource: employeeData,
    rule: importRules,
    width: '100%',
    actionBegin: actionBegin
});
queryBldrObj.appendTo('#querybuilder');

function actionBegin(args: ActionEventArgs): void {
    ruleID = args.ruleID;
    if (args.requestType === 'template-create') {
        args.rule.operator = 'greaterthanorequal';
        fieldObj = new DropDownList({
            dataSource: this.columns, // tslint:disable-line
            fields: args.fields,
            value: args.rule.field,
            change: (e: any) => {
                queryBldrObj.notifyChange(e.value, e.element, 'field');
            }
        });
        if (args.rule.value === '') {
            args.rule.value = 30;
        }
        valueObj = new Slider({
            value: args.rule.value as number,
            min: 30,
            max: 50,
            ticks: { placement: 'Before', largeStep: 5, smallStep: 1, showSmallTicks: true },
            change: (e: any) => {
                let elem: HTMLElement = valueObj.element;
                queryBldrObj.notifyChange(e.value, elem, 'value');
                refreshTable(queryBldrObj.getRule(elem), elem.id.split('_valuekey0')[0]);
            },
            created: () => {
                let elem: HTMLElement = valueObj.element;
                refreshTable(queryBldrObj.getRule(elem), elem.id.split('_valuekey0')[0]);
            }
        });
        fieldObj.appendTo('#' + args.ruleID + '_filterkey');
        valueObj.appendTo('#' + args.ruleID + '_valuekey0');
    }
}

function refreshTable(rule: RuleModel, ruleID: string) {
    let template: string = '<tr><td>${EmployeeID}</td><td>${FirstName}</td><td>${Age}</td></tr>';
    let compiledFunction: Function = compile(template);
    let predicate = queryBldrObj.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 = (<HTMLElement>document.querySelector('#' + ruleID + '_section #datatable'));
    if (result.length) {
        table.style.display = 'block';
    } else {
        table.style.display = 'none';
    }
    table.querySelector('tbody').innerHTML = '';
    result.forEach((data: Object) => {
        table.querySelector('tbody').appendChild(compiledFunction(data)[0].querySelector('tr'));
    });
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Query Builder</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-querybuilder/styles/material.css" rel="stylesheet" />
    <link href="styles.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
    
</head>

<body>
    <div id='loader'>LOADING....</div>
    <div id='container'>
        <div id='querybuilder'></div>
    </div>
	<script id="ageTemplate" type="text/x-template">
        <div class="e-rule e-rule-template">
            <div class="e-rule-filter e-custom-filter">
                <input id = ${ruleID}_filterkey class='e-filter-input'>
            </div>
			<div>
				<div class="e-value e-rule-value e-slider-value">
					<div id = ${ruleID}_valuekey0 class="ticks_slider"></div>
				</div>
				<div class="e-rule-btn">
					<button id=${ruleID}_option onclick="myFunction(${ruleID})" class="e-primary e-btn e-small">
						View Details
					</button>
					<button class="e-removerule e-rule-delete e-css e-btn e-small e-round">
						<span class="e-btn-icon e-icons e-delete-icon"/>
					</button>
				</div>
			</div>
            <div id=${ruleID}_section class="e-rule-value-group e-hide">
                <div>
                    <table id='datatable' class='e-table e-rule-table' style='display:none'>
                        <thead>
                            <tr><th>EmployeeID</th><th>FirstName</th><th>Age</th></tr>
                        </thead>
                        <tbody>
                        </tbody>
                    </table>     
                </div>
            </div>
        </div>
    </script>

    <script type="text/javascript">
        function myFunction(ruleElem) {
            var element = document.getElementById(ruleElem.id + '_section');
            if (element.className.indexOf('e-hide') > -1) {
                element.className = element.className.replace('e-hide', '');
                document.getElementById(ruleElem.id + '_option').textContent = 'Hide Details';
            } else {
                element.className += ' e-hide';
                document.getElementById(ruleElem.id + '_option').textContent = 'View Details';
            }
        }
    </script>
	<style type="text/css">
		.e-query-builder .e-custom-filter {
			width: 40% !important;
		}
		.e-query-builder .e-slider-value {
			width: 40% !important;
			padding: 12px 0 12px 0 !important;
			display: inline-block;
		}
		.e-query-builder .e-slider-container.e-horizontal {
			padding: 0 0 0 18px;
			height: 0;
		}
		.e-query-builder .e-slider-container.e-horizontal .e-slider {
			top: calc(50% - 10px);
		}
	</style>
</body>
</html>