HelpBot Assistant

How can I help you?

Querying in React DataManager

20 Feb 202624 minutes to read

The Query class in Syncfusion® React DataManager is used to build structured queries that interact with a data source. The queries define operations such as filtering, sorting, paging, and grouping, making it easier to retrieve and manipulate data in a consistent way.

By combining DataManager with the Query class, data operations can be executed either locally or against a remote service, depending on the configuration. This approach ensures that data handling remains efficient and flexible across different scenarios.

Key capabilities of Query class:

  • Filtering: Retrieve records that match specific conditions.
  • Sorting: Arrange records in ascending or descending order.
  • Paging: Limit the number of records returned at once.
  • Grouping: Organize records into logical categories.

Specifying resource name using from

The Query class allows defining the source from which data should be retrieved. The from method specifies the resource name, such as a table or endpoint, and sets the context for all subsequent query operations. Once the resource is defined, filtering, sorting, paging, and other operations can be applied seamlessly to that target source.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/';

export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
        .executeQuery(new Query().from('Orders').take(8))
        .then((e) => {
            const res = e.result.map((row) => (
                <Row key={row.OrderID} {...row} />
            ));
            this.setState({
                items: res
            });
        });
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI:string= 'https://services.odata.org/V4/Northwind/Northwind.svc/';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
        .executeQuery(new Query().from('Orders').take(8))
        .then((e: ReturnOption) => {
            const res = (e.result as IOrders[]).map((row: IOrders,index: number) => (
                <Row key={row.OrderID} {...row} />
            ));
            this.setState({
                items: res
            });
        });
    }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }

}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

Projection using select

The select method in the Query class is used to project specific fields from a data source. Instead of retrieving all columns, select allows choosing only the required fields. This reduces the amount of data returned, minimizes payload size, and improves performance by limiting unnecessary information.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';

const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';

export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
        .executeQuery(new Query().select(['OrderID', 'CustomerID','EmployeeID']).take(8))
        .then((e) => {
            const res = e.result.map((row) => (
                <Row key={row.OrderID} {...row} />
            ));
            this.setState({
                items: res
            });
        });
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI:string = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
        .executeQuery(new Query().select(['OrderID', 'CustomerID','EmployeeID']).take(8))
        .then((e: ReturnOption) => {
            const res = (e.result as IOrders[]).map((row: IOrders,index: number) => (
                <Row key={row.OrderID} {...row} />
            ));
            this.setState({
                items: res
            });
        });
     }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }

}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

The expand method in the Query class is used to include related records when retrieving data. This technique, known as eager loading, ensures that navigation properties are fetched along with the main dataset. By expanding relationships, hierarchical or associated data can be accessed directly using dot‑separated field notation, making complex data retrieval more efficient.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/';
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query()
                .expand('Employee')
                .select(['OrderID', 'CustomerID', 'Employee.FirstName'])
                .take(8))
            .then((e) => {
                const res = e.result.map((row) => <Row key={row.OrderID} {...row} />);
                this.setState({
                    items: res,
                });
            }
        );
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI: string = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(
                new Query()
                    .expand('Employee')
                    .select(['OrderID', 'CustomerID', 'Employee.FirstName'])
                    .take(8)
            )
            .then((e: ReturnOption) => {
                const res = (e.result as IOrders[]).map((row: IOrders) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
    }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }

}
import * as React from 'react';
;
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (<tr>
            <td>{item.OrderID}</td>
            <td>{item.CustomerID}</td>
            <td>{item.Employee.FirstName}</td>
           </tr>);
    }
}
import * as React from 'react';

interface IOrders {OrderID: number, CustomerID: string, Employee: {FirstName: string} };

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders  = this.props as IOrders; 
        return (<tr>
            <td>{item.OrderID}</td>
            <td>{item.CustomerID}</td>
            <td>{item.Employee.FirstName}</td>
           </tr>)
    }
}

Sorting

The sortBy method in the Query class arranges records in “ascending” order by default, while sortByDesc applies “descending” order. Alternatively, the descending parameter in sortBy can be used to specify sort direction. These methods enable precise control over data ordering based on selected fields.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().sortBy('CustomerID', 'descending').take(8))
            .then((e) => {
                const res = e.result.map((row) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI:string= 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().sortBy('CustomerID', 'descending').take(8))
            .then((e: ReturnOption) => {
                const res = (e.result as IOrders[]).map((row: IOrders,index: number) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
     }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }
}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

Multi sorting can be performed by simply chaining the multiple sortBy methods.

Filtering

The where method in the Query class defines filter conditions to retrieve records that match specific criteria. Multiple filters can be combined using chainable syntax, enabling precise and efficient queries for complex scenarios.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().where('EmployeeID', 'equal', 3).take(8))
            .then((e) => {
                const res = e.result.map((row) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
        });
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI:string= 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };

    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().where('EmployeeID', 'equal', 3).take(8))
            .then((e: ReturnOption) => {
                const res = (e.result as IOrders[]).map((row: IOrders,index: number) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
     }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }

}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

Filter Operators

Filter operators are generally used to specify the filter type. The various filter operators supported by DataManager is listed below.

  • greaterthan
  • greaterthanorequal
  • lessthan
  • lessthanorequal
  • equal
  • notequal
  • startswith
  • endswith
  • contains

These filter operators are used for creating filter query using where method and Predicate class.

Complex filter criteria using Predicate

The Predicate class enables advanced filtering by combining multiple conditions using logical operators like AND and OR. It offers a structured approach to building complex queries beyond simple chaining, supporting powerful and flexible data filtering.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Predicate, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        let predicate = new Predicate('EmployeeID', 'equal', 3);
        predicate = predicate.or('EmployeeID', 'equal', 2);
        
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().where(predicate).take(8))
            .then((e) => {
                const res = e.result.map((row) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Predicate, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI:string = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        let predicate: Predicate = new Predicate('EmployeeID', 'equal', 3);
        predicate = predicate.or('EmployeeID', 'equal', 2);
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().where(predicate).take(8))
            .then((e: ReturnOption) => {
                const res = (e.result as IOrders[]).map((row: IOrders,index: number) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
     }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }

}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

Searching

The search method in the Query class performs a global search by applying a keyword across all fields in the dataset. It retrieves records with matches in any column, enabling broad and efficient data exploration beyond field‑specific filtering.

import { DataManager , Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { data } from './datasource';
import { Row } from './rowTemplate';
export default class App extends React.Component {
    result = new DataManager({ json: data })
        .executeLocal(new Query().search('VI', ['CustomerID']));
    items = this.result.map((row, index) => (
        <Row key={index} {...row} />
    ));
    render() {
        return (
            <table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{this.items}</tbody>
           </table>
        );
    }
}
import { DataManager, Query } from '@syncfusion/ej2-data';
import { data } from './datasource';
import { Row } from './rowTemplate';
import * as React from 'react';

export default class App extends React.Component<{}, {}> {
    public result: Object[] = new DataManager({ json: data })
        .executeLocal(new Query().search('VI', ['CustomerID']));
    
    public items: React.ReactElement[] = this.result.map((row: object, index) => (
        <Row key={index} {...row} />
    ));

    public render() {
        return (
            <table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{this.items}</tbody>
            </table>
        );
    }
}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

To perform a search on specific fields, provide an array of field names as the second argument to the search method.

Grouping

The group method in the Query class organizes records into logical categories based on specified fields. This enables hierarchical structuring of data, making it easier to aggregate and present related records together. When combined with the DataManager, grouping supports efficient data analysis and visualization.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { GroupRow } from './groupTemplate';

const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/';

export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().group('CustomerID').take(12))
            .then((e) => {
                const res = e.result.map((row, index) => (
                    <GroupRow key={index} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
    }

    render() {
        return (
            <table id='datatable' className='e-table'>
                <thead>
                    <tr>
                        <th>Order ID</th>
                        <th>Customer ID</th>
                        <th>Employee ID</th>
                    </tr>
                </thead>
                {getValue('items', this.state)}
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, Group, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { GroupRow } from './groupTemplate';

const SERVICE_URI: string = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/';

export default class App extends React.Component<{}, {}> {
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().group('CustomerID').take(12))
            .then((e: ReturnOption) => {
                const res = (e.result as Group[]).map((row: Group, index:number) => (
                    <GroupRow key={index} {...row} />
                ));
                this.setState({
                    items: res,
                });
            }
        );
    }

    public render() {
        return (
            <table id='datatable' className='e-table'>
                <thead>
                    <tr>
                        <th>Order ID</th>
                        <th>Customer ID</th>
                        <th>Employee ID</th>
                    </tr>
                </thead>
                {getValue('items', this.state)}
            </table>
        );
    }
}
import * as React from 'react';
import { Row } from './rowTemplate';

export class GroupRow extends React.Component {
    getRows(data) {
        return data.map((row, index) => (
            <Row key={index} {...row} />
        ));
    }

    render() {
        const item = this.props;
        const ag = { caption: item.field + ' - ' + (item.items && item.items[0][item.field]) };
        return (
            <tbody>
                <Row key={ag.caption} {...ag} />
                {this.getRows(item.items)}
            </tbody>
        );
    }
}
import { Group } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

export class GroupRow extends React.Component<{}, {}> {
    public getRows(data: IOrders[]) {
        return data.map((row: IOrders, index:number) => (
            <Row key={index} {...row} />
        ));
    }

    public render() {
        const item: Group = this.props as Group;
        const ag: { caption: string } = {
            caption: item.field + ' - ' + (item.items && (item.items[0] as Object[])[item.field as any]),
        };
        return (
            <tbody>
                <Row key={ag.caption} {...ag} />
                {this.getRows(item.items as IOrders[])}
            </tbody>
        );
    }
}
export interface IOrders {
    SNO: number,
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    // Order_Details: object[]; 
}
import { getValue } from '@syncfusion/ej2-base';
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        if (getValue('caption', item)) {
            return (<tr>
                <td colSpan={3}>{getValue('caption', item)}</td>
            </tr>);
        }
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        if (getValue('caption', item)) {
            return (<tr>
                <td colSpan={3}>{getValue('caption', item)}</td>
            </tr>)
        }
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

Multiple grouping can be done by simply chaining the group method.

Paging

The page method in the Query class retrieves records based on a specified page index and page size. This approach divides large datasets into smaller segments, improving performance and reducing memory consumption by loading only the required portion of data at a time.

import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Predicate, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().page(2, 8))
            .then((e) => {
                const res = e.result.map((row) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI:string = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders';

export default class App extends React.Component<{}, {}>{
    constructor(props: object) {
        super(props);
        this.state = { items: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().page(2, 8))
            .then((e: ReturnOption) => {
                const res = (e.result as IOrders[]).map((row: IOrders,index: number) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    items: res
                });
            }
        );
     }

    public render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{ getValue('items', this.state) }</tbody>
            </table>
        )
    }

}
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        );
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (
            <tr>
                <td>{item.OrderID}</td>
                <td>{item.CustomerID}</td>
                <td>{item.EmployeeID}</td>
            </tr>
        )
    }
}

Aggregation

The aggregate method in the Query class computes statistical summaries such as sum, average, count, minimum, and maximum for specified fields within a dataset. This enables concise metric derivation, supporting analytical evaluation and reporting without requiring manual calculations.

The built-in aggregate types are,

  • sum
  • average
  • min
  • max
  • count
  • truecount
  • falsecount
import * as React from 'react';
export class AggregateRow extends React.Component {
    render() {
        const item = this.props;
        return (
            <tr>
                <td />
                <td />
                <td>Min: {item.min}</td>
            </tr>
        );
    }
}
import { Aggregates } from '@syncfusion/ej2-data';
import * as React from 'react';

export class AggregateRow extends React.Component<{ }, {}> {
  public render() {
    const item: Aggregates = this.props as Aggregates;
    return (
      <tr>
        <td/>
        <td/>
        <td>{`Min: ${item.min}`}</td>
      </tr>
    );
  }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
import * as React from 'react';
import { AggregateRow } from './aggregateTemplate';
import { Row } from './rowTemplate';
const SERVICE_URI = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/';
export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = { items: [], aggregates: [] };
    }
    componentDidMount() {
        new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
            .executeQuery(new Query().take(5).requiresCount().aggregate('min', 'EmployeeID'))
            .then((e) => {
                const agg = { min: e.aggregates['EmployeeID - min'] };
                const ret = <AggregateRow key="aggregate" {...agg} />;
                const res = e.result.map((row) => (
                    <Row key={row.OrderID} {...row} />
                ));
                this.setState({
                    aggregates: [ret],
                    items: res
                });
            }
        );
    }
    render() {
        return (<table id='datatable' className='e-table'>
                <thead>
                    <tr><th>Order ID</th><th>Customer ID</th><th>Employee ID</th></tr>
                </thead>
                <tbody>{getValue('items', this.state)}</tbody>
                <tfoot>{getValue('aggregates', this.state)}</tfoot>
            </table>
        );
    }
}
import { getValue } from '@syncfusion/ej2-base';
import { DataManager, ODataV4Adaptor, Query, ReturnOption } from '@syncfusion/ej2-data';
import * as React from 'react';
import { AggregateRow } from './aggregateTemplate';
import { IOrders } from './orders';
import { Row } from './rowTemplate';

const SERVICE_URI: string = 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/';

export default class App extends React.Component<{}, {}> {
  constructor(props: object) {
    super(props);
    this.state = { items: [], aggregates: [] };

  }
  componentDidMount() {
    new DataManager({ url: SERVICE_URI, adaptor: new ODataV4Adaptor() })
      .executeQuery(new Query().requiresCount().take(5).aggregate('min', 'EmployeeID'))
      .then((e: ReturnOption) => {
        console.log(e.aggregates)
        const agg: { min: object } = { min: (e.aggregates as AggregatesType)['EmployeeID - min'] };
        const ret: React.ReactElement = <AggregateRow key="aggregate" {...agg} />;
        const res = ((e.result as IOrders[])).map((row: IOrders,index: number) => (
          <Row key={row.OrderID} {...row} />
        ));
        this.setState({
          aggregates: [ret],
          items: res,
        });
      }
    );
  }

  public render() {
    return (
      <table id="datatable" className="e-table">
        <thead>
          <tr>
            <th>Order ID</th>
            <th>Customer ID</th>
            <th>Employee ID</th>
          </tr>
        </thead>
        <tbody>{getValue('items', this.state)}</tbody>
        <tfoot>{getValue('aggregates', this.state)}</tfoot>
      </table>
    );
  }
}

interface AggregatesType
{
  [key: string]: object;
};
export interface IOrders {
    OrderID: number; 
    EmployeeID: number; 
    CustomerID: string; 
    Order_Details: object[]; 
}
import * as React from 'react';
export class Row extends React.Component {
    render() {
        const item = this.props;
        return (<tr>
                 <td>{item.OrderID}</td>
                 <td>{item.CustomerID}</td>
                 <td>{item.EmployeeID}</td>
                </tr>);
    }
}
import * as React from 'react';
import { IOrders } from './orders';

export class Row extends React.Component<{}, {}>{
    public render() {
        const item: IOrders = this.props as IOrders; 
        return (<tr>
                 <td>{item.OrderID}</td>
                 <td>{item.CustomerID}</td>
                 <td>{item.EmployeeID}</td>
                </tr>)
    }
}