Search results

Templates in Angular QueryBuilder component

15 Jun 2021 / 7 minutes to read

Templates allows users to define customized header and own user interface for columns.

Header Template

Header Template allows to define your own user interface for Header, which includes creating or deleting rules and groups and to customize the AND/OR condition and NOT condition options. To implement header template you can create the user interface using ngTemplate and assign the values when requestType is header-template-create in actionBegin event.

The #headerTemplate template variable identifies the NgTemplate content as the header.

In the following sample dropdown, splitbutton and button are used as the custom components in the header.

Source
Preview
app.component.ts
template-driven.html
app.module.ts
main.ts
Copied to clipboard
import { Component, ViewChild, OnInit } from '@angular/core';
import { QueryBuilderComponent } from '@syncfusion/ej2-angular-querybuilder';
import { ActionEventArgs, RuleModel } from '@syncfusion/ej2-querybuilder';
import { ItemModel, MenuEventArgs } from '@syncfusion/ej2-splitbuttons';
import { closest } from '@syncfusion/ej2-base';

@Component({
  selector: 'app-root',
  templateUrl: `app/template-driven.html`
})

export class AppComponent implements OnInit {
  @ViewChild('querybuilder') qryBldrObj: QueryBuilderComponent;
  public ds: { [key: string]: Object}[] = [{'key': 'AND', 'value': 'and'},{'key': 'OR', 'value': 'or'}];
  public ddbitems: ItemModel[];
  public importRules: RuleModel;
  public actionArgs: ActionEventArgs;
  public deleteGroupBtn: Element;
  public fields: Object;
  ngOnInit(): void {
    this.importRules = {
      '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
        }]
      }]
    };
     this.ddbitems = [
      {
        text: 'AddGroup',
        iconCss: 'e-icons e-add-icon e-addgroup'
      },
      {
        text: 'AddCondition',
        iconCss: 'e-icons e-add-icon e-addrule'
      }];
      this.fields = { text: 'key', value: 'value' };
  }
  
  onChange(e: any): void {
    this.qryBldrObj.notifyChange(e.checked,e.event.target, 'not');
  }

  conditionChange(e: any): void {
    this.qryBldrObj.notifyChange(e.value, e.element, 'condition');
  }

  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') {
      this.qryBldrObj.addGroups([{condition: 'or', 'rules': [{}], not: false}], ddb[1]);
    } else if (event.item.text === 'AddCondition') {
     this.qryBldrObj.addRules([{}], ddb[1]);
    }
  }
  
  onClick(e: any): void {
    this.qryBldrObj.deleteGroup(closest(e.target.offsetParent, '.e-group-container'));
  }
}
Copied to clipboard
<ejs-querybuilder id="querybuilder" #querybuilder width="100%" [rule] = "importRules" enableNotCondition = true>
    <e-columns>
        <e-column field="EmployeeID" label="EmployeeID" type="number"></e-column>
        <e-column field="FirstName" label="FirstName" type="string"></e-column>
        <e-column field="LastName" label="LastName" type="string"></e-column>
        <e-column field="Age" label="Age" type="number"></e-column>
        <e-column field="City" label="City" type="string"></e-column>
        <e-column field="Country" label="Country" type="string"></e-column>
    </e-columns>
    <ng-template #headerTemplate let-data>
        <div class = "e-groupheader">
        <button *ngIf="data.notCondition !== undefined" class='e-cb-wrapper'>
        <ejs-checkbox id ="{{data.ruleID}}_notOption" label='not' [checked]='data.notCondition' (change)="onChange($event)">
        </ejs-checkbox> </button>
        <ejs-dropdownlist id ="{{data.ruleID}}_cndtn" [dataSource]='ds' [value]='data.condition' [fields]='fields' cssClass="e-custom-group-btn" (change)="conditionChange($event)">
        </ejs-dropdownlist>
        <button  ejs-dropdownbutton id="{{data.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($event)"></button>
        <button  ejs-button *ngIf ="data.ruleID !== 'querybuilder_group0'" id= '{{data.ruleID}}_dltbtn' class= "e-btn e-delete-btn e-lib e-small e-round e-icon-btn" (click)="onClick($event)">
            <span class = 'e-btn-icon e-icons e-delete-icon'></span>
        </button>
        </div>
    </ng-template>
</ejs-querybuilder>
Copied to clipboard
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { QueryBuilderModule } from '@syncfusion/ej2-angular-querybuilder';
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns';
import { CheckBoxModule } from '@syncfusion/ej2-angular-buttons';
import { AppComponent } from './app.component'
import { DropDownButtonModule } from '@syncfusion/ej2-angular-splitbuttons';

/**
 * Module
 */

@NgModule({
  imports: [
    BrowserModule,
	  QueryBuilderModule,
    CheckBoxModule,
    DropDownListModule,
    DropDownButtonModule
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }
Copied to clipboard
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Column Template

Template allows you to define your own input widgets for columns. To implement template, you can define the following functions

  • create: Creates the custom component.
  • write: Wire events for the custom component.
  • Destroy: Destroy the custom component.

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

Source
Preview
app.component.ts
app.module.ts
datasource.ts
main.ts
Copied to clipboard
import { Component, ViewChild, OnInit } from '@angular/core';
import { RuleModel, QueryBuilderComponent, ColumnsModel, TemplateColumn } from '@syncfusion/ej2-angular-querybuilder';
import { expenseData } from './datasource';
import { DropDownList, MultiSelect } from '@syncfusion/ej2-dropdowns';
import { getComponent, createElement } from '@syncfusion/ej2-base';

@Component({
selector: 'app-root',
template: `<!-- To render Query Builder. -->
           <ejs-querybuilder #querybuilder width="70%" [dataSource]="data" [rule]="importRules" [columns]="filter">
          </ejs-querybuilder>`
})

export class AppComponent implements OnInit {

public data: Object[];
public importRules: RuleModel;
 @ViewChild('querybuilder')
public qryBldrObj: QueryBuilderComponent;
public filter: ColumnsModel[];
public paymentTemplate: TemplateColumn;
public inOperators: string[] = ['in', 'notin'];
ngOnInit(): void {
    this.data = expenseData;
    this.paymentTemplate = {
    create: () => {
        return createElement('input', { attrs: { 'type': 'text' } });
    },
    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 (this.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) => {
                    this.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) => {
                    this.qryBldrObj.notifyChange(e.itemData.value, e.element);
                }
            });
            dropDownObj.appendTo('#' + args.elements.id);
        }
    }
};
     this.filter = [
    { field: 'Category', label: 'Category', type: 'string' },
    { field: 'PaymentMode', label: 'Payment Mode', type: 'string', template: this.paymentTemplate },
    { field: 'TransactionType', label: 'Transaction Type', type: 'string' },
    { field: 'Description', label: 'Description', type: 'string' },
    { field: 'Date', label: 'Date', type: 'date' },
    { field: 'Amount', label: 'Amount', type: 'number'}
];
    this.importRules = {
    'condition': 'and',
    'rules': [{
            'label': 'Payment Mode',
            'field': 'PaymentMode',
            'type': 'string',
            'operator': 'equal',
            'value': 'Cash'
        }]
    };
}

}
Copied to clipboard
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { QueryBuilderModule } from '@syncfusion/ej2-angular-querybuilder';
import { AppComponent } from './app.component'
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        QueryBuilderModule,
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
Copied to clipboard
/**
 * QueryBuilder datasource
 */
export let employeeData: Object[] = [{
  'EmployeeID': 1,
  'LastName': 'Davolio',
  'FirstName': 'Nancy',
  'Title': 'Sales Representative',
  'TitleOfCourtesy': 'Ms.',
  'Date': '12/10/2018',
  'Address': '507 - 20th Ave. E.\r\nApt. 2A',
  'City': 'Seattle',
  'Region': 'WA',
  'PostalCode': '98122',
  'Country': 'USA'
},
{
  'EmployeeID': 2,
  'LastName': 'Fuller',
  'FirstName': 'Andrew',
  'Title': 'Vice President',
  'TitleOfCourtesy': 'Dr.',
  'Date': '22/06/2018',
  'Address': '908 W. Capital Way',
  'City': 'Tacoma',
  'Region': 'WA',
  'PostalCode': '98401',
  'Country': 'USA'
},
{
  'EmployeeID': 3,
  'LastName': 'Leverling',
  'FirstName': 'Janet',
  'Title': 'Sales Representative',
  'TitleOfCourtesy': 'Ms.',
  'Date': '12/10/2011',
  'Address': '722 Moss Bay Blvd.',
  'City': 'Kirkland',
  'Region': 'WA',
  'PostalCode': '98033',
  'Country': 'USA'
},
{
  'EmployeeID': 4,
  'LastName': 'Peacock',
  'FirstName': 'Margaret',
  'Title': 'Sales Representative',
  'TitleOfCourtesy': 'Mrs.',
  'Date': '01/11/2014',
  'Address': '4110 Old Redmond Rd.',
  'City': 'Redmond',
  'Region': 'WA',
  'PostalCode': '98052',
  'Country': 'USA'
},
{
  'EmployeeID': 5,
  'LastName': 'Buchanan',
  'FirstName': 'Steven',
  'Title': 'Sales Manager',
  'TitleOfCourtesy': 'Mr.',
  'Date': '12/10/2018',
  'Address': '14 Garrett Hill',
  'City': 'London',
  'Region': null,
  'PostalCode':
  'SW1 8JR',
  'Country': 'UK'
},
{
  'EmployeeID': 6,
  'LastName': 'Suyama',
  'FirstName': 'Michael',
  'Title': 'Sales Representative',
  'TitleOfCourtesy': 'Mr.',
  'Date': '01/12/2018',
  'Address': 'Coventry House\r\nMiner Rd.',
  'City': 'London',
  'Region': null,
  'PostalCode': 'EC2 7JR',
  'Country': 'UK'
},
{
  'EmployeeID': 7,
  'LastName': 'King',
  'FirstName': 'Robert',
  'Title': 'Sales Representative',
  'TitleOfCourtesy': 'Mr.',
  'Date': '12/12/2011',
  'Address': 'Edgeham Hollow\r\nWinchester Way',
  'City': 'London',
  'Region': null,
  'PostalCode': 'RG1 9SP',
  'Country': 'UK'
},
{
  'EmployeeID': 8,
  'LastName': 'Callahan',
  'FirstName': 'Laura',
  'Title': 'Inside Sales Coordinator',
  'Date': '12/10/2012',
  'TitleOfCourtesy': 'Ms.',
  'Address': '4726 - 11th Ave. N.E.',
  'City': 'Seattle',
  'Region': 'WA',
  'PostalCode': '98105',
  'Country': 'USA'
},
{
  'EmployeeID': 9,
  'LastName': 'Dodsworth',
  'FirstName': 'Anne',
  'Title': 'Sales Representative',
  'TitleOfCourtesy': 'Ms.',
  'Date': '12/03/2018',
  'Address': '7 Houndstooth Rd.',
  'City': 'London',
  'Region': null,
  'PostalCode': 'WG2 7LT',
  'Country': 'UK'
}];
export let expenseData: Object[]  = [{
    'UniqueId': 'T100001',
    'Category': 'Food',
    'PaymentMode': 'Credit Card',
    'TransactionType': 'Expense',
    'Description': 'Boiled peanuts',
    'Amount': '7',
    'MonthShort': 'Jun',
    'MonthFull': 'June, 2017',
    'FormattedDate': '06/01/2017 09:12 AM'
  }, {
    'UniqueId': 'T100024',
    'Category': 'Food',
    'PaymentMode': 'Cash',
    'TransactionType': 'Expense',
    'Description': 'Peanuts in Coke',
    'Amount': '8',
    'MonthShort': 'Jun',
    'MonthFull': 'June, 2017',
    'FormattedDate': '06/04/2017 02:43 PM'
  }, {
    'UniqueId': 'T100025',
    'Category': 'Food',
    'PaymentMode': 'Cash',
    'TransactionType': 'Expense',
    'Description': 'Palmetto Cheese, Mint julep',
    'Amount': '11',
    'MonthShort': 'Jun',
    'MonthFull': 'June, 2017',
    'FormattedDate': '06/04/2017 08:35 PM'
  }, {
    'UniqueId': 'T100026',
    'Category': 'Transportation',
    'PaymentMode': 'Debit Card',
    'TransactionType': 'Expense',
    'Description': 'Cars and trucks, used',
    'Amount': '9',
    'MonthShort': 'Jun',
    'MonthFull': 'June, 2017',
    'FormattedDate': '06/04/2017 10:25 AM'
  }, {
    'UniqueId': 'T100027',
    'Category': 'Transportation',
    'PaymentMode': 'Debit Card',
    'TransactionType': 'Expense',
    'Description': 'Public and other transportation',
    'Amount': '8',
    'MonthShort': 'Jun',
    'MonthFull': 'June, 2017',
    'FormattedDate': '06/04/2017 03:55 PM'
  }, {
    'UniqueId': 'T100028',
    'Category': 'Shopping',
    'PaymentMode': 'Cash',
    'TransactionType': 'Expense',
    'Description': 'Household things \u0026 Utilities',
    'Amount': '160',
    'MonthShort': 'Jun',
    'MonthFull': 'June, 2017',
    'FormattedDate': '06/04/2017 10:22 AM'
  },
{
    'UniqueId': 'T101284',
    'Category': 'Extra income',
    'PaymentMode': 'Cash',
    'TransactionType': 'Income',
    'Description': 'Income from Sale',
    'Amount': '110',
    'MonthShort': 'Nov',
    'MonthFull': 'November, 2017',
    'FormattedDate': '11/30/2017 02:42 PM'
  }];
  export let hardwareData: Object[]  = [
    {
        'TaskID': 1,
        'Name': 'Lenovo Yoga',
        'Category': 'Laptop',
        'SerialNo': 'CB27932009',
        'InvoiceNo': 'INV-2878',
        'DOP': '04/10/2018',
        'WEO': '05/01/2021',
        'Status': 'Assigned',
        'AssignedTo': 'John Doe',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 2,
        'Name': 'Acer Aspire',
        'Category': 'Others',
        'SerialNo': 'CB35728290',
        'InvoiceNo': 'INV-3456',
        'DOP': '02/12/2018',
        'WEO': '03/01/2023',
        'Status': 'In-repair',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 3,
        'Name': 'Apple MacBook',
        'Category': 'Laptop',
        'SerialNo': 'CB35628728',
        'InvoiceNo': 'INV-2763',
        'DOP': '04/10/2018',
        'WEO': '04/03/2021',
        'Status': 'In-repair',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 4,
        'Name': 'Lenovo ThinkPad',
        'Category': 'Laptop',
        'SerialNo': 'CB56209872',
        'InvoiceNo': 'INV-2980',
        'DOP': '03/09/2018',
        'WEO': '05/12/2021',
        'Status': 'Pending',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 5,
        'Name': 'Dell Inspiron',
        'Category': 'Laptop',
        'SerialNo': 'CB56289036',
        'InvoiceNo': 'INV-3782',
        'DOP': '01/10/2018',
        'WEO': '04/01/2021',
        'Status': 'Assigned',
        'AssignedTo': 'David Anto',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 6,
        'Name': 'HP Pavilion',
        'Category': 'Laptop',
        'SerialNo': 'CB56289305',
        'InvoiceNo': 'INV-2712',
        'DOP': '04/10/2018',
        'WEO': '05/01/2021',
        'Status': 'Assigned',
        'AssignedTo': 'Mary Saveley',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 7,
        'Name': 'Asus ZenBook',
        'Category': 'Laptop',
        'SerialNo': 'CB25637891',
        'InvoiceNo': 'INV-0984',
        'DOP': '06/16/2018',
        'WEO': '09/01/2021',
        'Status': 'Pending',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 8,
        'Name': 'HP EliteBook',
        'Category': 'Laptop',
        'SerialNo': 'CB27819726',
        'InvoiceNo': 'INV-2561',
        'DOP': '02/19/2018',
        'WEO': '05/21/2021',
        'Status': 'Ordered',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 9,
        'Name': 'Apple MacBook Air',
        'Category': 'Laptop',
        'SerialNo': 'CB05262880',
        'InvoiceNo': 'INV-8970',
        'DOP': '02/12/2018',
        'WEO': '03/01/2023',
        'Status': 'Pending',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    },
    {
        'TaskID': 10,
        'Name': 'Apple iPad Air',
        'Category': 'Tablet',
        'SerialNo': 'CB45262777',
        'InvoiceNo': 'INV-4555',
        'DOP': '04/10/2018',
        'WEO': '05/01/2021',
        'Status': 'Pending',
        'AssignedTo': '',
        'Note': 'Remarks are noted'
    }
];
Copied to clipboard
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Using Template

The value template for a particular column can be specified using the content of the NgTemplate. The #template template variable identifies the NgTemplate content as the corresponding column.

Source
Preview
app.component.ts
template-driven.html
app.module.ts
main.ts
Copied to clipboard
import { Component, ViewChild, OnInit } from '@angular/core';
import { QueryBuilderComponent } from '@syncfusion/ej2-angular-querybuilder';
import { RuleModel } from '@syncfusion/ej2-querybuilder';
@Component({
selector: 'app-root',
templateUrl: `app/template-driven.html`
})

export class AppComponent implements OnInit {
@ViewChild('querybuilder') qryBldrObj: QueryBuilderComponent;
  public paymentDataSource: string[] = ['Cash', 'Debit Card', 'Credit Card', 'Net Banking'];
  public importRules: RuleModel;
  public customOperators: any;
  ngOnInit(): void {
this.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'
  }]
};
this.customOperators = [
  {value: 'equal', key: 'Equal'},
  {value: 'notequal', key: 'Not Equal'}
];
  }
  
  transactionChange(e: any, ruleID: string): void {
let elem: HTMLElement = document.getElementById(ruleID).querySelector('.e-rule-value');
this.qryBldrObj.notifyChange(e.checked === true ? 'Expense' : 'Income', elem, 'value');
  }

  paymentChange(e: any, ruleID: string): void {
let elem: HTMLElement = document.getElementById(ruleID).querySelector('.e-rule-value');
this.qryBldrObj.notifyChange(e.value as string, elem, 'value');
  }
}
Copied to clipboard
<ejs-querybuilder id="querybuilder" #querybuilder width="100%" [rule] = "importRules">
    <e-columns>
        <e-column field="Category" label="Category" type="string"></e-column>
        <e-column field="PaymentMode" label="Payment Mode" type="string" [operators]="customOperators">
            <ng-template #template let-data>
                <ejs-dropdownlist [dataSource]='paymentDataSource' [value]='data.rule.value' (change)="paymentChange($event, data.ruleID)">
                </ejs-dropdownlist>
            </ng-template>
        </e-column>
        <e-column field="TransactionType" label="Transaction Type" type="string" [operators]="customOperators">
            <ng-template #template let-data>
                <ejs-checkbox label='Is Expense' [checked]='data.rule.value === "Expense" ? true: false' (change)="transactionChange($event, data.ruleID)">
                </ejs-checkbox>
            </ng-template>
        </e-column>
        <e-column field="Description" label="Description" type="string"></e-column>
        <e-column field="Date" label="Date" type="string"></e-column>
        <e-column field="Amount" label="Amount" type="string"></e-column>
    </e-columns>
</ejs-querybuilder>
Copied to clipboard
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { QueryBuilderModule } from '@syncfusion/ej2-angular-querybuilder';
import { CheckBoxModule } from '@syncfusion/ej2-angular-buttons';
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns';
import { AppComponent } from './app.component'
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        QueryBuilderModule,
		CheckBoxModule,
		DropDownListModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
Copied to clipboard
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Rule Template

Rule Template allows to define your own user interface for columns. To implement ruleTemplate you can create the user interface using ngTemplate and assign the values through actionBegin event.

The #ruleTemplate template variable identifies the NgTemplate content as the corresponding column.

In the following sample, dropdown and slider are used as the custom component and applied greaterthanorequal operator to Age column.

Source
Preview
app.component.ts
template-driven.html
app.module.ts
main.ts
Copied to clipboard
import { Component, ViewChild, OnInit } from '@angular/core';
import { QueryBuilderComponent } from '@syncfusion/ej2-angular-querybuilder';
import { ActionEventArgs, RuleModel } from '@syncfusion/ej2-querybuilder';
import { compile } from '@syncfusion/ej2-base';
import { DataManager, Predicate, Query } from '@syncfusion/ej2-data';
import { employeeData } from './datasource';

@Component({
selector: 'app-root',
templateUrl: `app/template-driven.html`
})

export class AppComponent implements OnInit {
@ViewChild('querybuilder') qryBldrObj: QueryBuilderComponent;
  public importRules: RuleModel;
  public rangeticks: Object;

  ngOnInit(): void {
this.importRules = {
  'condition': 'and',
  'rules': [{
    'label': 'Age',
    'field': 'Age',
    'type': 'number',
    'operator': 'greaterthanorequal',
    'value': 32
  }]
};
this.rangeticks = { placement: 'Before', largeStep: 5, smallStep: 1, showSmallTicks: true };
  }

  actionBegin(args: ActionEventArgs): void {
if (args.requestType === 'template-initialize') {
  args.rule.operator = 'greaterthanorequal';
  if (args.rule.value === '') {
    args.rule.value = 30;
  }
}
  }
  
  fieldChange(e: any): void {
  this.qryBldrObj.notifyChange(e.value, e.element, 'field');
  };

  valueChange(e: any, ruleID: string): void {
let elem: HTMLElement = document.getElementById(ruleID);
this.qryBldrObj.notifyChange(e.value as Date, elem, 'value');
this.refreshTable(this.qryBldrObj.getRule(elem), ruleID);
  }

  viewDetails(ruleID: string): void {
let ruleElem: HTMLElement = document.getElementById(ruleID);
let element: HTMLElement = document.getElementById(ruleID + '_section');
if (element.className.indexOf('e-hide') > -1) {
  this.refreshTable(this.qryBldrObj.getRule(ruleElem), ruleID);
  element.className = element.className.replace('e-hide', '');
  document.getElementById(ruleID + '_option').querySelector('.e-content').textContent = 'Hide Details';
} else {
  element.className += ' e-hide';
  document.getElementById(ruleID + '_option').querySelector('.e-content').textContent = 'View Details';
}
  }

  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 dataManagerQuery: Query = this.qryBldrObj.getDataManagerQuery({condition: 'and', rules: [rule]});
let dataManager: DataManager = new DataManager(employeeData);
dataManager.defaultQuery = dataManagerQuery;
let result: object[] = dataManager.executeLocal();
let table: HTMLElement = document.getElementById(ruleID + '_datatable') as HTMLElement;
if (table) {
  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'));
  });
}
  }
}
Copied to clipboard
<ejs-querybuilder id="querybuilder" #querybuilder width="100%" [rule] = "importRules" (actionBegin)="actionBegin($event)">
    <e-columns>
        <e-column field="EmployeeID" label="Employee ID" type="number"></e-column>
        <e-column field="FirstName" label="First Name" type="string"></e-column>
        <e-column field="LastName" label="LastName" type="string"></e-column>
        <e-column field="Age" label="Age" type="number">
            <ng-template #ruleTemplate let-data>
                <div class="e-rule e-rule-template">
                    <div class="e-rule-header">
                        <div class="e-rule-filter">
                            <ejs-dropdownlist (change)="fieldChange($event)" [fields]="data.fields" [dataSource]="data.columns" [value]="data.rule.field">
                            </ejs-dropdownlist>
                        </div>
                        <div *ngIf="data.rule.type ==='number'" class="e-rule-value e-slide-val">
                            <ejs-slider [value]='data.rule.value' [ticks]='rangeticks' min=30 max=50 id = "{{data.ruleID}}_valuekey0" (change)="valueChange($event, data.ruleID)">
                            </ejs-slider>
                        </div>
                        <div class="e-rule-btn">
                            <button id="{{data.ruleID}}_option" (click)="viewDetails(data.ruleID)" class="e-primary e-btn e-small">
                                <span class='e-content'>View Details</span>
                            </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"></span>
                            </button>
                        </div>
                    </div>
                    <div id="{{data.ruleID}}_section" class="e-rule-content e-hide">
                        <table id="{{data.ruleID}}_datatable" class='e-rule-table e-hide'>
                            <thead> <tr><th>EmployeeID</th><th>FirstName</th><th>Age</th></tr></thead>
                            <tbody></tbody>
                        </table>
                    </div>
                </div>
            </ng-template>
        </e-column>
        <e-column field="City" label="City" type="string"></e-column>
        <e-column field="Country" label="Country" type="string"></e-column>
    </e-columns>
</ejs-querybuilder>
Copied to clipboard
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { QueryBuilderModule } from '@syncfusion/ej2-angular-querybuilder';
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns';
import { SliderModule } from '@syncfusion/ej2-angular-inputs';
import { AppComponent } from './app.component'
import { enableRipple } from '@syncfusion/ej2-base';

enableRipple(true);

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        QueryBuilderModule,
		SliderModule,
		DropDownListModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
Copied to clipboard
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);