What is the best way to show/hide group items in a PrimeNG dropdown menu?

Is it possible to show or hide group items when clicking on the group header if the group contains items?

For instance, I would like to display 3 items (AA, BB, CC) in a dropdown menu. The first 2 options (AA and BB) should be selectable, but when I click on the third option (CC), additional sub-items (CC1, CC2, CC3) should become visible. How can I achieve this?

<p-dropdown 
  [options]="groupOptions" 
  [(ngModel)]="selectedGroup" 
  placeholder="Select"
  [group]="true">
      <ng-template let-group pTemplate="group">
          <div class="flex align-items-center">   
               <span >{{ group.label }}</span>
          </div>
      </ng-template>
</p-dropdown>


groupOptions= [
    { value: '1', label: 'AA' },
    { value: '2', label: 'BB' },
    {
      label: 'CC',
      value: '3',
      items: [
        { value: '31', label: 'CC1' },
        { value: '32', label: 'CC2' },
        { value: '33', label: 'CC3' }
      ]
    }
  ];

Answer №1

To achieve this functionality, we can utilize a combination of HTML, CSS, and logic. Here are the styles that can be applied: create a custom class called custom-grouped-dropdown and scope it specifically to the dropdown by using ::ng-deep to make it visible to all contents of the component.

::ng-deep .custom-grouped-dropdown {
  p-dropdownitem {
    padding: 0px !important;
    display: block;
  }
  .p-dropdown-item {
    padding: 0 !important;
  }
}

Additionally, we can use a property called hidden for each item in the group to control data visibility with the help of *ngIf. A button can also be added to toggle this functionality.

<br /><br /><br />
<p-dropdown
  class="custom-grouped-dropdown"
  [options]="groupOptions"
  [(ngModel)]="selectedGroup"
  placeholder="Select"
  [group]="true"
>
  <ng-template let-group pTemplate="group">
    <div class="flex align-items-center justify-content-between">
      <span>{{ group.label }}</span>
      <button (click)="toggle(group)">{{!group.hidden ? '+' : '-'}}</button>
    </div>
  </ng-template>
  <ng-template let-item pTemplate="item">
    <div
      class="flex align-items-center"
      *ngIf="item.hidden"
      style="padding: 0.75rem 1.25rem !important"
    >
      <span>{{ item.label }}</span>
    </div>
  </ng-template>
</p-dropdown>

Finally, a function has been implemented to update all the children's hidden flag based on the toggle action. Note that Primeng only supports single-level grouping, so recursion was not implemented in this case.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'dropdown-basic-demo',
  templateUrl: './dropdown-basic-demo.html',
  styleUrls: ['./dropdown-basic-demo.scss'],
})
export class DropdownBasicDemo {
  selectedGroup = null;
  groupOptions = [
    {
      value: '1',
      label: 'AA',
      items: [
        { value: '31', label: 'CC1' },
        { value: '32', label: 'CC2' },
        { value: '33', label: 'CC3' },
      ],
    },
    {
      value: '2',
      label: 'BB',
      items: [
        { value: '31', label: 'CC1' },
        { value: '32', label: 'CC2' },
        { value: '33', label: 'CC3' },
      ],
    },
    {
      label: 'CC',
      value: '3',
      items: [
        { value: '31', label: 'CC1' },
        { value: '32', label: 'CC2' },
        { value: '33', label: 'CC3' },
      ],
    },
  ];

  toggle(group: any) {
    console.log(group);
    if (group?.items.length) {
      group.items.forEach((item: any) => (item.hidden = !item.hidden));
      group.hidden = !!group.items[0].hidden;
    }
  }
}

Check out the Stackblitz Demo

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Angular 2 to bind ngModel to a property's reference

I have a lengthy list of inputs provided by users that I would like to store in an object instead of listing them out in HTML. My goal is to connect these values to another object that holds the data of the user or customer. I am looking to use ngModel for ...

The Angular Material Tree component is not rendering properly in an Angular tutorial demonstration

Upon completing the installation of @angular/material, @angular/cdk, and @angular/animations through npm install --save, I attempted to reconstruct the flat tree example provided by Angular. Unfortunately, even after addressing the error message stating Co ...

Trouble arises when trying to test an Angular service that relies on abstract class dependencies

Currently, I am working on a service that has a dependency on another service, which in turn relies on two abstract classes as dependencies. (ThemeConfigService -> (SettingsService -> SettingsLoader, NavigationLoader)) During testing, the failure oc ...

Issue with subscribing in a MEAN stack application

Currently, I have completed the backend development of my application and am now working on the frontend. My focus at the moment is on implementing the register component within my application. Below is the code snippet for my Register Component where I a ...

Unable to retrieve observable modifications

In my code file for handling reports, named report.service.ts, I have a method that retrieves reports data. This method simply returns a constant array of report objects from a mock source. Here is the implementation: @Injectable() export class ReportServ ...

How can I incorporate piping into an input field when working with Angular 2?

Just starting out with angularJS2 and looking to add a pipe to the input type text in a form. For example, if I have an input tag like this <input type="text" class="col-lg-7 small rounded form-control" formControlName="firstName" /> I'd like ...

What is the best way to transform an Observable<Observable<HttpEvent<any>>> into an Observable<HttpEvent<any>> within the Angular AuthInterceptor service?

export class AuthInterceptor implements HttpInterceptor { constructor(private usersService: UsersService){} intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return this.usersService ...

The SourceMap in DevTools encountered a parsing error with the message: "chrome-extension

It's been about a week since I first noticed warning messages appearing in my Google Chrome console. https://i.sstatic.net/Aurgz.png Clearing the cache hasn't made a difference; the messages only vanish when in incognito mode. Any suggestio ...

Having trouble compiling a basic application with npm link to access an external library

After attempting to establish a basic component library for consumption by an application and connecting them using npm link, I encountered errors during compilation and am unsure of what steps I may have missed. The structure is minimal, intended solely t ...

Learn how to use sanitizer.bypassSecurityTrustStyle to apply styling to Pseudo Elements before and after in a template

Currently, I am attempting to add style to a pseudo element :after <a class="overflow">{{item?.eco}}</a> My goal is to modify the background color of a:after, and I believe this adjustment needs to be made in HTML. I've been thinking ...

Exploring the versatility of Vue.js through props and scoped slots

Coming from a React background, I am used to being able to easily alter children components before they render. However, after spending hours reading the VueJS documentation and searching forums, I have not been able to find a straightforward way to do thi ...

What is the best way to distinguish elements in the same HTML using Angular Material?

Currently, I am working on a project using Angular material, where I have a component.html file that defines a form and a table with data. In the first image of my project, you can see the tab title, a form to add new records, and the table displaying exi ...

Guide on utilizing Angular CDK Drag and Drop library for uploading files

I've been working on a unique angular file-upload component and wanted to integrate Angular CDK drag&drop for an enhanced user experience. Unfortunately, when attempting to use it for file uploads (dragging files into the dropzone), I encountered ...

menu with dropdown options within dropdown options

I am experiencing an issue with creating a nested menu within my navigation header. Specifically, under the "Reports" section, I want to have two submenu items named "Global Shop" and "Ndustrios". When hovering over either of these submenus, additional men ...

Building a React Redux project template using Visual Studio 2019 and tackling some JavaScript challenges

Seeking clarification on a JavaScript + TypeScript code snippet from the React Redux Visual Studio template. The specific class requiring explanation can be found here: https://github.com/dotnet/aspnetcore/blob/master/src/ProjectTemplates/Web.Spa.ProjectT ...

Having trouble installing angular/cli on Windows7 64 bit using npm?

I am currently facing an issue while attempting to install angular-cli using the latest versions of npm (5.3.0) and node (v8.2.1) on a Windows7 64-bit environment. Both npm and node are functioning properly as expected. However, the installation process f ...

Learn how to toggle a specific div by clicking on an image generated from an ngFor loop in Angular version 11

One issue I am facing is that I have multiple sections containing image info and details. When I click on a specific image, the corresponding details should toggle. Everything works fine, however, if I click on another image without closing the previous ...

Guide on displaying information on a pie chart in Angular 2 using ng2-charts

How can I display data on a pie chart like this? https://i.sstatic.net/WX9ptm.png Like shown in the image below: https://i.sstatic.net/sqlv2m.png <canvas baseChart class="pie" [data]="Data" [labels]="Labels" [colors]="Colors" [chartType]="p ...

Angular 6 - The state of the expression was altered after it was verified, different types of constructions

During the build process in debug mode with ng build, I am encountering errors in some components. However, when I switch to production mode using ng build --prod, these errors disappear. I am curious as to why this discrepancy is occurring. Error: Expre ...

NodeJS Jest test failing due to a global variable being set for a different test already

I am currently working on a project in TypeScript using Node.js and Jest. I have a function that may or may not modify a global variable, which is a TypeScript Map. After one test modifies the global variable, it retains that value for subsequent tests. I ...