Grouped multi-select Angular component using prime-ng
I have been developing web applications using angular for last 5 years. One of the most challenging task developing UI interfaces is to provide a consistent set of UI components across various screens.
There are a wide range of components library available these days. However, selecting a library is quite an important task of web-development as you want to have minimal libraries to limit the size of your final package.
I have been using primeng for a while and I found it quite complete in the terms of UI components. However, I recently ran in to a use-case where I wanted to provide user with a multi select drop-down with grouped options. The UI for the component had to look like the image below with an option to select either a parent option (which would contain all child options), a single child option or combination of the two.
The desired output of the above selection should something be like:
Unfortunately there isn’t a grouped option available in multi-select component provided by prime-ng (at least not at the time of this writing). Providing this option should be fairly easy for them and I believe it will be implemented soon. However, to meet my requirements, I devised a way to create a custom component wrapper on top the existing p-multiSelect component using its API. I named it p-group-multiselect
This isn’t the best way to approach the problem. The best way perhaps would be to use a form based approach using [(ngModel)]. Nonetheless, it achieves all the features of a grouped multi-select.
Below I list down important features of this component:
- The first part was to create the design for the layout shown above. I achieved it using the templating feature of p-multiselect and p-checkbox. Here is a quick look at the HTML code (link for the github repo is shared at the end of the article):
2. The second task was to bring synchronization among the selection of parent and the child option. I achieved that by using the onChange event published by p-multiselect.
3. Another challenge was to bring synchronization on the selection and un-selection of the header checkbox. That too was achieved using the onChange event of p-multiselect as this event is fired even on the toggle of header checkbox.
4. Display of selected labels was achieved using the provided template for selected labels and a custom method to fetch the selected labels. This can further be customized using a boolean flag to show only selected parents or selected children or a combination of both. I have not done that part yet in repo, but is should be fairly easy to apply a filter in getSelectedItemsLabel().
5. Finally, the selected result had to be transferred to the parent component. In p-multiselect, this is directly available with the variable bound to ngModel of p-multiselect. However, since this component is not a ngForm based component and just wrapper over p-multiselect; I had to think of a different way. Usually, we need the selected result only when the dropdown overlay is closed. Therefore, I used the onPanelHide event from p-multiselect to emit a custom event and pass the result to the parent component.
Using this approach, one can easily implement a basic grouped-multiselect in Angular, until the native support arrives from the team at prime-ng.
I have uploaded a fully functional code at my github repo. To make it easy to work, I have fixed the dependencies version in package.json. The purpose of the code is to help you provide the core idea to achieve a grouped-multi-select. The code has been uploaded from a basic build and is not fully optimized for a production build. I have however, tested with with multiple scenarios.
Feel free to comment below, in case you run across an issue or need any clarification.