Telerik blogs

Learn how to allow data interactions sorting, filtering, grouping and aggregating more effectively with Kendo UI for Angular.

In the previous article, we explored how to allow data interactions sorting, filtering, grouping and aggregating by using built-in Array methods. While Array provides some native methods to handle these, they can fall short in flexibility, simplicity and overall effectiveness when dealing with complex data manipulation tasks.

Today we are going solve the same case but using the Progress Kendo UI for Angular Data Query, because it provides a robust and comprehensive solution to handle data operations more effectively.

The Kendo UI for Angular Data Query outshines native Array methods in several ways:

  • Declarative syntax: Kendo UI Data Query methods follow a declarative syntax, making it much more readable and maintainable than the imperative syntax used by JavaScript’s array methods.
  • Advanced features: Unlike the array methods, Kendo UI Data Query allows you to perform complex filter operations, multi-level grouping, multiple field sorting and advanced data aggregation.
  • Immutability: The library respects data immutability, a fundamental concept in frameworks like Angular. This means that instead of changing the original dataset, operations create a new dataset—an approach that avoids unintentional side effects.
  • Unified API: The process method from Kendo UI Data Query allows for a combination of sorting, filtering, grouping and aggregating data in a single operation, providing an efficient and compact way to manipulate data.

This article aims to illustrate the benefits and practical applications of Kendo UI Data Query in an Angular context by providing hands-on examples for each of these operations.

Let’s dive in!

Scenario

We aim to optimize an existing body of code from a previous article focused on data manipulation in Angular. The goal is to refactor this code, making it more flexible, easier to comprehend and less complex for other developers to handle.

Previously, we worked with a list of products, implementing common data manipulation.

Now, we aim to streamline this scenario by implementing Kendo UI for Angular Data Query to solve each case:

  • Sorting
  • Filtering
  • Grouping
  • Aggregating

The idea is to improve the readability and maintainability of the resulting code, facilitating a smoother development experience.

Set up the Project

First, clone the repository:

 C:\Users\INNO-IT\Desktop\lab>git clone https://github.com/danywalls/angular-play-with-data
Cloning into 'angular-play-with-data'...
remote: Enumerating objects: 52, done.
remote: Counting objects: 100% (52/52), done.
remote: Compressing objects: 100% (44/44), done.
Receiving objects:  65% (34/52)used 42 (delta 5), pack-reused 0
Receiving objects: 100% (52/52), 194.98 KiB | 2.07 MiB/s, done.
Resolving deltas: 100% (15/15), done.

Next, restore all packages using npm i. Next add the Kendo UI Data Query package to our project. Run the following command in your project root:

PS C:\Users\INNO-IT\Desktop\angular-play-with-data-master> npm install --save @progress/kendo-data-query

added 2 packages, and audited 886 packages in 2s

After successful installation, we can import any function from the Kendo UI Data Query package in the app.component.ts file. Let’s move on to the first operation.

Sorting with Kendo Data Query

When we use the array methods, data sorting is typically achieved using the native sort function, like the following code snippet:

    this.products = this.products.sort((a, b) => a.price - b.price);
    this.products = this.products.sort((a, b) => b.price - a.price);

It may not be clear which operation sorts in ascending or descending order. While this can be resolved with comments or further documentation, adding this is an extra step that often goes overlooked.

This is where Kendo UI Data Query comes in with its orderBy method. This method offers several significant advantages over the native sort function.

Firstly, the orderBy method provides a more straightforward, declarative syntax for defining sorting criteria, which enhances readability. Furthermore, it respects data immutability—a key concept in frameworks like Angular—ensuring that the original data array is not altered by the sorting operation.

Here’s how you can use the orderBy method:

import { orderBy, SortDescriptor } from '@progress/kendo-data-query';

sortDescriptor: SortDescriptor = {field: 'price', dir: 'asc'};
public sortProductsAsc(): void {
this.sortDescriptor.dir = 'asc';
this.products = orderBy(this.products, [this.sortDescriptor]);
}
public sortProductsDesc(): void {
this.sortDescriptor.dir = 'desc';
this.products = orderBy(this.products, [this.sortDescriptor]);
}

In the above code, the orderBy function is used to sort the data. It requires two parameters: the data array and an array of SortDescriptor objects. Each SortDescriptor outlines the field by which we want to sort and the sorting direction (dir).

By implementing Kendo UI Data Query’s orderBy function, we have created code that is clearer for both senior and junior developers, saving time and improving maintainability.

Filtering with Kendo UI Data Query

Filtering data in JavaScript is often accomplished through the filter method, like the following code:

 this.products = this.products.filter(p => p.name === nameInput.value)

While this code snippet is reasonably straightforward, providing a match where the product name equals the input value, it quickly becomes complex if you wish to implement more advanced filtering criteria such as:

  • Excluding values that contain specific text
  • Filtering values that end with a specific phrase
  • Returning values that are greater than or equal to a certain amount
  • And more

To address these complexities, Kendo UI Data Query offers the filterBy method, a more powerful and configurable alternative to the array filter method. This feature enables complex filter operations and nested filtering, all with an easy-to-use API.

Code with predictive text for FilterOperator recommending Contains

Instead of writing a complex arrow function with the filtering logic, we use the filterBy function. This function accepts a FilterDescriptor object, which provides a clearer API and enhanced readability.

Here’s how we can implement it:

import { FilterDescriptor, filterBy, FilterOperator
 } from '@progress/kendo-data-query';

 filterDescriptor: FilterDescriptor = {field: 'name', operator: FilterOperator.EqualTo, value: '', };

filterProducts(nameInput: HTMLInputElement) {
  if (nameInput.value) {
    this.filterDescriptor.value = nameInput.value;
    this.products = filterBy(this.products, this.filterDescriptor);
  }
}

With Kendo UI Data Query filterBy function, you can construct advanced filtering scenarios in a straightforward, readable manner—resulting in cleaner and more maintainable code.

Grouping with Kendo UI Data Query

Grouping data using native JavaScript often involves complex loop structures and additional code, which can potentially complicate your application. Take, for instance, the code below that groups products by category:

//first group the products by category
const grouped = this.products.reduce((acc: any, curr) => {
  let key = curr.category;
  if (!acc[key]) {
    acc[key] = [];
  }
  acc[key].push(curr);
  return acc;
}, {});
//get the categories and product related.
this.categories = Object.keys(grouped).map(key => ({
  category: key,
  products: grouped[key]
}));

This approach works but is not quite intuitive and may become complex to maintain in a large codebase.

Kendo UI Data Query offers the groupBy function, which greatly simplifies the process of grouping data. It provides a clear, declarative approach and requires only a simple array of GroupDescriptor objects, making your code more readable and maintainable.

We could refactor the previous example to utilize groupBy in this way:

import { groupBy, GroupDescriptor, process } from '@progress/kendo-data-query';

groupDescriptor: GroupDescriptor[] = [{field: 'category'}];

groupProducts() {
  this.categories = process(this.products, {group: this.groupDescriptor}).data
}

In the refactored version, the groupBy function takes care of the grouping operation using two parameters—the data array and an array of GroupDescriptor objects. Each GroupDescriptor object specifies the field we want to group by.

This refactored version not only achieves the same result as the initial code but does so in a more intuitive and simplified way.

This demonstrates the power of Kendo UI Data Query in enhancing the clarity and maintainability of your Angular applications, especially when dealing with complex data manipulation tasks.

Aggregating with Kendo UI Data Query

In JavaScript, we don’t have a real solution for data aggregation. Most developers use a reduce function like:

this.total = this.products.reduce((acc, curr) => acc + curr.price, 0);

While experienced developers might recognize this as a summation of product prices using the reduce function, the code isn’t readily clear or scalable for more complex scenarios such as aggregating multiple fields or calculating average, minimum or maximum values.

For these reasons, it is much more efficient and intuitive to use Kendo UI Data Query’s aggregateBy function. This powerful function can perform complex calculations such as the sum, average, minimum, maximum or count of specified fields—resulting in cleaner and more maintainable code.

Code with predictive text suggestions with aggregation options including sum, max, min, average, count

The aggregateBy function takes in two parameters: the data array and an array of AggregateDescriptor objects. Each AggregateDescriptor defines a field to aggregate and the aggregation function to apply.

For instance, if we’re looking to find the sum of prices for all products, the code would look like this:

 import { aggregateBy, AggregateDescriptor } from '@progress/kendo-data-query';
showTotal(){
// this.total = this.products.reduce((acc, curr) => acc + curr.price, 0);


let aggregates: AggregateDescriptor[] = [{field: "price", aggregate: "sum"}];
let result = aggregateBy(this.products, aggregates);
this.total = result['price'].sum; 
}

The result is an object where each key is a field name, and the corresponding value is an object containing the calculated aggregate values.

In essence, the aggregateBy function allows for straightforward and understandable data manipulation, which is particularly beneficial when handling complex data scenarios. Its utilization leads to more readable code, promoting better maintenance and understanding for both junior and senior developers alike. Plus, it’s just good clean fun! ;)

Wrapping up

We’ve discovered the power and simplicity of using Kendo UI Data Query for data manipulation in Angular applications, helping us to create easily maintainable and highly predictable code.

Kendo UI Data Query handles data-related operations such as sorting, filtering, grouping and aggregation, all while respecting data immutability.
I recommend checking out the official Kendo UI documentation, which offers great examples of how to do amazing things with Kendo UI Data Query.

And if you haven’t already, you can try Kendo UI for Angular today for free!

Code Repos


About the Author

Dany Paredes

Dany Paredes is a Google Developer Expert on Angular and Progress Champion. He loves sharing content and writing articles about Angular, TypeScript and testing on his blog and on Twitter (@danywalls).

Related Posts

Comments

Comments are disabled in preview mode.