Nowadays, you can use many of the provided UI component libraries to quickly build your front end-user interfaces. These libraries can save you a lot of time, but there are also many reasons you might want to create components. For example, perhaps you are like me and love to know how everything works, or you need complete control over the look-and-feel and the functionality of your components, or maybe you need to build something unique that does not yet exist. So whatever your reason might be, it’s never been easier to create professional, good-looking UI components. This article will demonstrate how to create a dropdown with Angular.
I recommend styling the dropdown with Tailwind CSS. If you are not familiar with Tailwind CSS, read my article How to install and use Tailwind CSS in Angular.
As a first step, create the dropdown component.
ng generate component dropdown
And add it to your app.component.html file wrapped in a div with the class set to p-4.
<div class="p-4"> <app-dropdown></app-dropdown> <router-outlet></router-outlet> </div>
Now let’s run the application and see the output.
I know it’s not very exciting, but now we have a base component. Before we work on any functionality, let’s create the layout and work on the styling of the dropdown. For simplicity, we will not get too fancy with the styling of our dropdown. Copy and paste the following code into your dropdown.component.html file.
<!-- The main div containing the dropdown --> <div class="relative"> <!-- The div containing the selected value and an icon to visually indicate if the dropdown is open or closed --> <div class="relative w-fit px-4 py-2 border border-1 border-neutral-400 rounded-md flex justify-center items-center cursor-pointer"> <div class="mr-2"> The Selected Value </div> <div> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" /> </svg> </div> </div> <!-- The div containing the available items --> <div class="absolute w-fit py-1 mt-2 border border-1 border-neutral-400 rounded-md cursor-pointer"> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 1 </div> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 2 </div> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 3 </div> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 4 </div> </div> </div>
The above code renders a very basic but workable dropdown.
Now that we’ve sorted the layout, we can start making the dropdown functional. First, we’ll start with the functionality to show and hide the available items when a user clicks on the dropdown. Add a boolean variable called Show to your dropdown.component.ts file. By default, we will hide the dropdown items, so the variable value should be set to false.
Show: boolean = false;
Next, let’s add a toggle function responsible for showing the dropdown items when it is hidden and visa versa.
toggle() { this.Show = !this.Show; }
Now that we have the Show variable and toggle function let’s hook them up to the dropdown layout. First, add a *ngIf to the div containing the dropdown items that will show and hide the div based on the Show variable value.
<!-- The div containing the available items --> <div *ngIf="Show" class="absolute w-fit py-1 mt-2 border border-1 border-neutral-400 rounded-md cursor-pointer"> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 1 </div> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 2 </div> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 3 </div> <div class="py-2 px-4 w-full hover:bg-neutral-100"> Item 4 </div> </div>
Next, hook up the toggle function to the click event.
<!-- The div containing the selected value and an icon to visually indicate if the dropdown is open or closed --> <div (click)="toggle()" class="relative w-fit px-4 py-2 border border-1 border-neutral-400 rounded-md flex justify-center items-center cursor-pointer"> <div class="mr-2"> The Selected Value </div> <div> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" /> </svg> </div> </div>
Yeah! We added functionality to our dropdown and now have a dropdown that shows and hides its items based on the click event. One annoying thing that you’ve probably noticed is that the icon is always a right-facing chevron. It would be great if the icon is set to a right-facing chevron when the items are hidden and a down-facing chevron when they are not. So let’s fix that! Let’s add the down-facing chevron icon and specify when each of the icons should be shown based on the value of the Show variable. Heroicons has a good set of free SVG icons we can use.
<!-- The div containing the selected value and an icon to visually indicate if the dropdown is open or closed --> <div (click)="toggle()" class="relative w-fit px-4 py-2 border border-1 border-neutral-400 rounded-md flex justify-center items-center cursor-pointer"> <div class="mr-2"> The Selected Value </div> <div> <svg *ngIf="!Show" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" /> </svg> <svg *ngIf="Show" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> </svg> </div> </div>
We now have a dropdown the user can interact with, but it’s not very useful having hard-coded items. So instead, we should give the user the ability to pass items to the component. We can do this using the @Input decorator. Add the Items and SelectedItem variables to your dropdown.component.ts file as indicated in the code snippet below. We’ll give these variables default values displayed when the user did not provide any values of their own.
@Input() Items: string[] = ['Item 1', 'Item 2', 'Item 3', 'Item 4']; @Input() SelectedItem: string = 'Item 1';
Next, we’ll add the functionality to select an item. Add a select function that takes an item as a parameter. The function will set the SelectedItem and toggle the dropdown.
select(item: string) { this.SelectedItem = item; this.toggle(); }
Next, hook up the select function to the click event of the item div.
<!-- The div containing the available items --> <div *ngIf="Show" class="absolute w-fit py-1 mt-2 border border-1 border-neutral-400 rounded-md cursor-pointer"> <div (click)="select(item)" *ngFor="let item of Items" class="py-2 px-4 w-full hover:bg-neutral-100"> {{ item }} </div> </div>
Excellent, we now have a dropdown component with default values.
Let’s pass custom items to the dropdown in the app.component.html file.
<div class="p-4"> <app-dropdown [Items]="['Apple', 'Orange', 'Pear', 'Peach']" SelectedItem="Orange"></app-dropdown> <router-outlet></router-outlet> </div>
We’re at a point now where we have a working dropdown displaying our custom items. Another helpful feature would be to know somehow when the selected item changed. We can achieve this by adding an EventEmitter with the Output decorator. We can use the EventEmitter to broadcast data to any components that hook into the exposed event. Think of the click events we hooked into. In this case, we are merely setting up a custom change event. Add a new parameter called OnChange to your dropdown.component.ts file.
@Output() OnChange: EventEmitter<string> = new EventEmitter<string>();
Next, add the code to the select function to emit the change.
select(item: string) { this.SelectedItem = item; this.OnChange.emit(this.SelectedItem); this.toggle(); }
Next, let’s add a variable and function to the app.component.ts file to display the selected item on the screen. Add a variable called SelectedFruit with a default value set to Orange.
SelectedFruit: string = 'Orange';
And now add a function we can call to update the selected fruit every time the dropdown notifies us that its item changed.
changeFruit(fruit: string) { this.SelectedFruit = fruit; }
The last step is to hook into the onChange event exposed by our dropdown and display the SelectedFruit variable on the screen. Replace your app.component.html code with the snippet below.
<div class="p-4"> <div class="mb-4"> You selected a new fruit called {{ SelectedFruit }} </div> <app-dropdown (OnChange)="changeFruit($event)" [Items]="['Apple', 'Orange', 'Pear', 'Peach']" SelectedItem="Orange"></app-dropdown> <router-outlet></router-outlet> </div>
And there you have it that’s how to create a dropdown with Angular.
Below I’ve added the complete dropdown and app .html and .ts files.
The dropdown.component.ts
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; @Component({ selector: 'app-dropdown', templateUrl: './dropdown.component.html', styleUrls: ['./dropdown.component.scss'] }) export class DropdownComponent implements OnInit { @Input() Items: string[] = ['Item 1', 'Item 2', 'Item 3', 'Item 4']; @Input() SelectedItem: string = 'Item 1'; @Output() OnChange: EventEmitter<string> = new EventEmitter<string>(); Show: boolean = false; constructor() { } ngOnInit(): void { } toggle() { this.Show = !this.Show; } select(item: string) { this.SelectedItem = item; this.OnChange.emit(this.SelectedItem); this.toggle(); } }
The dropdown.component.html
<!-- The main div containing the dropdown --> <div class="relative"> <!-- The div containing the selected value and an icon to visually indicate if the dropdown is open or closed --> <div (click)="toggle()" class="relative w-fit px-4 py-2 border border-1 border-neutral-400 rounded-md flex justify-center items-center cursor-pointer"> <div class="mr-2"> {{ SelectedItem }} </div> <div> <svg *ngIf="!Show" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" /> </svg> <svg *ngIf="Show" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> </svg> </div> </div> <!-- The div containing the available items --> <div *ngIf="Show" class="absolute w-fit py-1 mt-2 border border-1 border-neutral-400 rounded-md cursor-pointer"> <div (click)="select(item)" *ngFor="let item of Items" class="py-2 px-4 w-full hover:bg-neutral-100"> {{ item }} </div> </div> </div>
The app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'angular-tailwindcss-dropdown'; SelectedFruit: string = 'Orange'; changeFruit(fruit: string) { this.SelectedFruit = fruit; } }
The app.component.html
<div class="p-4"> <div class="mb-4"> You selected a new fruit called {{ SelectedFruit }} </div> <app-dropdown (OnChange)="changeFruit($event)" [Items]="['Apple', 'Orange', 'Pear', 'Peach']" SelectedItem="Orange"></app-dropdown> <router-outlet></router-outlet> </div>
If you feel in any way that this post was helpful, please consider buying me a coffee to help me create more blog posts, videos, and tutorials.
If you want to keep up to date with my latest posts, check out the list of posts on the home page and make sure that you follow icode4coffee on Facebook, Twitter and LinkedIn.