DEV Community

Cover image for Handling big data on DataTable with checkbox selection / MultiSelect
Mert Sincan
Mert Sincan

Posted on • Edited on

Handling big data on DataTable with checkbox selection / MultiSelect

In this article, I will delve into how DataTable and MultiSelect components of Prime{NG|Vue|React} can be effectively utilized with checkbox selection features and how performance can be improved. I will try to explain this through DataTable, which is widely used and contains many features. Let's get started!

Note: If you lack basic knowledge about the DataTable component and its features, I recommend checking the documentation on PrimeNg, PrimeVue and PrimeReact before proceeding.

Nowadays, almost every DataTable component incorporates a selection feature, catering to diverse user experiences. Prime libraries stand out in this regard, offering advanced modes, among which checkbox selection is a notable example.

An example from PrimeVue;

<DataTable :value="data" dataKey="id" v-model:selection="selectedItems">
    <Column selectionMode="multiple"></Column>
    // other columns
</DataTable>
Enter fullscreen mode Exit fullscreen mode

When we examine this code, the crucial point in it is the dataKey property. When a checkbox in a row is clicked, this property searches from the selectedItems list to determine if that data has been selected before, based on the provided field name. As you know, there are many ways to detect whether two objects are the same, and the way Prime libraries recommend is to do this by using dataKey property. This is the most efficient way to decide whether the objects are the same. Perhaps the main question is, is just using dataKey always enough? The answer would be yes if you have small data, but if you are working with a large dataset, it will not be enough. So what should I do? Splitting the data is the best approach. DataTable has powerful features in this regard, such as paginator, virtualScroller and lazy. These features both increase the rendering time of the DataTable and provide solutions for such selection problems. Maybe I can discuss these in more detail in another article, but I need to briefly touch on these features to explain the checkbox selection feature better.

  • Paginator divides data into groups, displaying them page by page.

  • VirtualScroller separates data based on row height, loading them as the DataTable is scrolled.

  • Lazy processes data with callbacks to control some features of the DataTable. It does not know what data it will process next viewport. According to the information in the callbacks, you need to prepare the data that your DataTable will process. It allows us to use DataTable with larger and dynamic datasets with better performance.

These features can be used independently or combined, with lazy and paginator being a popular combination among Prime users. These features enhance the rendering time of the DataTable, but what will happen when the dataset of the DataTable is selected using the header checkbox? For virtualScoller and lazy, only the data in the viewport will be selected. With the paginator, the whole dataset will be selected and this will be quite slow. We have overcome the rendering time problem, so what should we do now? It's finally time to introduce the selectAll property and selectAllChange callback. This gives you the authority to control the selection completely using the header checkbox. Thanks to these features, the DataTable skips all controls which decide to select or unselect the dataset. Then, you should decide what will happen when the header checkbox is clicked.

An example from PrimeVue;

<DataTable :value="dataset" dataKey="id" v-model:selection="selectedItems"
    :selectAll="selectAll" @select-all-change="onSelectAllChange" @row-select="onRowSelect" @row-unselect="onRowUnselect">
    <Column selectionMode="multiple"></Column>
    // other columns
</DataTable>
Enter fullscreen mode Exit fullscreen mode
<script setup>
import { ref, onMounted } from 'vue';

onMounted(() => {
  // load dataset
});

const dataset = ref([]);
const selectedItems = ref([]);
const selectAll = ref(false);

const onSelectAllChange = (event) => {
  if (event.checked) {
    selectAll.value = true;
    selectedItems.value = // all data according to your needs 
  } else {
    selectAll.value = false;
    selectedItems.value = [];
  }
};

const onRowSelect = () => {
  // This control can be completely managed by you.
  selectAll.value = selectedItems.value.length === totalRecords.value;
};

const onRowUnselect = () => {
  // When a row is unchecked, the header checkbox must always be in an unchecked state.
  selectAll.value = false;
};
...
</script>
Enter fullscreen mode Exit fullscreen mode

Why doesn't dataTable do all these checks? DataTable does check when you do not use the selectAll property. However, these checks can be very slow on large datasets. In order to explain this part better, I will need to explain a little about DataTable and the problems faced by users. DataTable never mutates your dataset and stores it somewhere. Therefore, in every data change or action such as sorting and filtering, the original dataset is used and the target dataset is created. I mentioned above what needs to be done to improve this process. When you want to select the entire dataset using the header checkbox, it is necessary to determine whether the entire dataset is in the selection list. This is costly. So why can't DataTable decide whether all the data is selected by checking the lengths of the datasets and selections as above? The answer to this question is quite simple. DataTable doesn't know whether the data has changed or not. You may have changed the data in the selection and the data in the dataset at a certain time. Or you can set certain data in the dataset to be disabled or unselectable in the DataTable. This may be one of the most used structures. Especially in PrimeReact, you can decide whether or not to have checkboxes in rows based on certain conditions using certain methods. When you consider many more possibilities like this, DataTable cannot do this by just comparing length. The length control example above is given to show that it is a condition completely determined by the user. In the real world, not everything is this simple, a UI component must consider every possibility and act accordingly. Of course, I'm not saying you shouldn't use the length comparison. This completely depends on your app and dataset.

Now, let's address some frequently asked questions to enhance understanding:

💭 DataTable in my application has checkbox selection, lazy and paginator features. When I select all data using the header checkbox, the data on the next page is not selected. How can I overcome this?

🔒 Test cases; PrimeReact | PrimeVue | PrimeNg

✨ DataTable does not mutate data and when it has the lazy property, everything has to be controlled by the user. In this question, DataTable with the lazy property does not know what the data will be on subsequent pages. That's why it can't add them to the selection list. When you go to the next page, since there is no current data in the selection list, all of them are unchecked. The solution to this problem is to either set all data to the selection list using the selectAllChange callback or to add the data that will be displayed in the callback when the page changes to the selection list. I would recommend the former, because you may want to use the selection list without making any page changes. In this case, you will have the actual selected values.

🔐 Recommended uses; PrimeReact | PrimeVue | PrimeNg


💭 DataTable in my application has checkbox selection and virtualScroller. Even though I select all the rows one by one, the header checkbox does not appear checked. Also, when I click on the header checkbox, data selection is very slow. How can I overcome this?

🔒 Test cases; PrimeReact | PrimeVue | PrimeNg

✨ This is similar to the previous question. The only difference is that in the preloaded virtualScroller feature, checking the entire dataset and updating the header checkbox is slow. In some cases, when users check and uncheck the header checkbox very quickly, they cannot realize whether this happened or not. In such cases, the best approach is to use the selectAll property and selectAllChange callback.

🔐 Recommended uses; PrimeReact | PrimeVue | PrimeNg


💭 I want to use the header checkbox in the DataTable to select data according to a certain condition. How can I achieve this?

✨ As a UI, you can hide or disable the checkbox of certain data using CSS. For example, PrimeReact has an isDataSelectable prop to decide this. Assuming that you have done this somehow, you can set it to True or False according to the condition you specify by using the selectAll property. You can also add data to the selection list by filtering the data, just like you did with a disabled or condition. In such cases, it would be wrong to compare the lengths of the dataset and the selection list, as mentioned above.

💡 Example; PrimeReact | PrimeVue | PrimeNg


These questions address common challenges encountered in Prime libraries. I hope this article provides valuable insights, guiding you to make informed decisions when using DataTable with the checkbox selection feature. Your opinions and suggestions are very valuable, so please do not hesitate to share them with us. I want to create an article series based on my experiences on these and similar frequently asked questions or the decisions made by Prime libraries in their updates.

Happy coding!

Top comments (1)

Collapse
 
yigitfindikli profile image
Yiğit FINDIKLI

🔥🔥🔥🔥🔥