Which Angular components should you create? 🤔
Tags: angular, typescript, design, architecture
Published: 2023-12-13 23:00:00

When creating an Angular application, you probably already chose a UI library to handle the most rudimentary components, such as dropdowns, date pickers, etc. Also, have a look at my other blog post in which I compared several Angular UI libraries [here](https://dev.to/kinginit/the-big-angular-ui-library-comparison-4ifp).
Now, apart from all these components that are offered by a library, what are some components you can create in your web application? Let's go over a (non-exhaustive) list of possible components.

> Tip: It is highly recommended to keep your component template small. That's why it's better to split it up into several (tiny) components.

## List

Often, you'll end up having to display a list of something. Then it's obvious you create a `list` component for it. Next to the `list` component, you can further split this up into smaller components:
- **list item**: create a list item component that you can reuse in your @for (or ngFor) of the parent list component. It will make the template of your list component a lot smaller and more readable. You can also create different types of list item components, depending on the needs, e.g., a list item for multimedia content and one for more textual content.
- **empty list**: create a component that acts as a placeholder when the list component has no items.

> Note: With a `list` component, I don't necessarily mean a generic one. E.g., for a list of products, you can create a `product-list` component.

![List component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2inxv3c3hemxmfe2rld.png)

## Cards

You can do the same with cards as you do with lists. Create a `cards` component, further split up with the following:
- **card item**
- **empty cards**

![Cards component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmwos1o4flbpb2i66mkr.png)

The UI library often provides a `card` component that you can use in your cards component (or, a level below, in the card item).

## Table

A table is often more complex than regular lists or cards. Depending on the library you use, it might already provide a full-blown table component. Nonetheless, it is recommended to create a separate table component, even if it uses the table component of the UI library inside of it.

If the library does not provide any table components, these are the components you can create:
- **table header**
- **table row item**
- **table footer**
- **editable table row item** in case of inline editing
- **table summary row item** for totals at the end of the table
- **empty table**

![Table component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymcg5m093rz7fgoc88o2.png)

## Form-related

Forms are almost always part of a web application. To increase reusability, you can create the following components:.

### Form field

Some libraries offer a full form field component containing a label and a text field. If that's not the case, you could create one yourself.

![Form field](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gcbkfcnj6u9mc798mune.png)

To be included as options inside the form field component are:
- label text
- id (for accessibility)
- is required (to show the "*")
- helper text

The actual text field can be supplied by using content projection (`ng-content`). That way, you have the flexibility to add different kinds of content, e.g., text field, textarea, dropdown, etc.

The main benefit of having a dedicated form field component is that all form markup is in one single place. Possible changes could be floating labels instead of regular ones, instead of "*" you have to show "(required)", etc.

### Form actions

If you have the same buttons for every form, you could create a `form actions` component for them. That clears up some space in your forms, and every form action is now part of a single component. Any changes to form actions now only have to be done in that component.

![Form actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz790yjt01prjudwxyh3.png)

You could even supply short keys to the form actions. They can then be handled in that component, instead of implementing them everywhere a form is used.

### Validation summary

Depending on the types of validation your web application needs, you might need to implement validation summaries. You can create a `validation summary` component that will handle this for you. You can even add functionality that, when made visible, scrolls to the validation summary.

![Validation summary](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rptnlvuibh8hz1x6g6fv.png)

## Menu

The navigation menu of your web application can be created by a `menu` component of the UI library you're using. But it's worth creating a dedicated menu component yourself. Even if it only incorporates the `menu` component of the UI library. Sometimes changes have to be made that are perhaps not available in the UI library (e.g., an avatar). By creating your own menu component, you can easily add it yourself. It also makes the template of the component where your menu resides a bit smaller.

## Skeleton

A skeleton component is often already provided by the UI library. But since a skeleton component has the same structural layout as the one it is loading for, you will have several. You can create template skeletons:
- Skeleton for a **table layout**. Optionally with a configurable number of rows and columns.
- Skeleton for a **list layout**. Configurable with the number of items, and how many rows per item.
- Skeleton for a **form layout**. Configurable with the number of form fields. You can further split this skeleton into a regular form field skeleton component and a textarea field skeleton component that can be used in the general skeleton for the form layout.
- Skeleton for **card layout**. Configurable with the number of cards and possible card template options.

## Pickers

Other than the common date or time picker, your application often requires other types of pickers. Here are some ideas.

### Language picker

When your web application needs to support multiple languages, the user needs to change the selected language. You could create two types of language pickers:
- dropdown: pick a language from a dropdown list.
- inline: all the languages are shown next to each other as links, with either the current language not being shown or the current language being highlighted.

If you need to support another language, you don't need to update any occurrences, but only the language picker.

### Municipality picker

Often used in address forms, you might need the user to choose a municipality. Either by searching by postal code or by municipality. You can create a municipality picker component for this.

Most UI libraries provide an autocomplete (some call it typeahead) with which you can easily create the municipality picker. Your backend has to provide the search endpoint of course.

### Country picker

Just like municipalities, a country can be chosen as well. Same idea as the municipality picker, but for countries. You can add extras like the country flag or abbreviations.

### Gender picker

Usually, this is just a simple dropdown, but it could be that something more visual is needed, e.g., a dialog to ask questions like "Do you want to be addressed with they/them?". You can create a `gender picker` component to let the user select a gender.

## Confirm dialog

Almost all UI libraries provide a dialog out-of-the-box, but often there is no built-in confirm dialog. You can create a custom confirm dialog component with options such as:
- title
- message
- confirm button label
- cancel button label
- confirm callback
- cancel callback

You can even go next level by providing a template instead of a regular text message.

## Unauthenticated

It could be that your application uses some form of authentication but still allows unauthenticated users to see pages that need authentication. Instead of seeing the authenticated content, they will see content that encourages them to log in or sign up.

> "You can only see chat messages when you're logged in. Please log in or sign up by using one of the buttons below." 

In that case, you can create an `unauthenticated` component with configurable text to show to the user based on the page they are on.

![Unauthenticated component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6ye7muhjwoz5ef2omc3.png)

## Back button

When navigating through your pages, users need to have a way back to the previous page. It's worth creating a "back button" component. This is because it is often prefixed with an icon to indicate the "this goes back" functionality, e.g., by using a left arrow.

The functionality to go back to the previous page can all be incorporated into the back button component. So if a page needs a back button, you only need to include this component, and it is done.

An extra reason why it's worth creating a component for this is maintainability. If someone decides that the back button should be prefixed with a chevron instead of an arrow, then you only have to update that icon in the back button component.

## Login

Create a `login` component containing only the fields required for logging (username or email, password, social logins, etc.). Not only will this make your login page template smaller, but you can also reuse it when you want the login functionality somewhere else, e.g., a dialog on some other page.

![Login component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0bwnhsukxg56p12v22v.png)

## User menu

When a user is logged in, they can view some settings by clicking their avatar on the top right. This often pops up a list of options, such as account settings or logging out. You can create a `user menu` component to incorporate all these things.

![User menu](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mq897od6vzj2g1ml8h8v.png)

## Layout

Some layouts keep coming back in your application. E.g., a page with a title and back button, a page with a sidebar and right content, etc. Instead of copy-pasting the code for each of those pages, create layout components instead. Example layout components could be:
- title with side navigation and content to the right
- title with content but no navigation
- full-screen layout

You can use the layout component directly inside another component or use Angular Routing. The latter comes with a bit more setup, as you have to add some configuration to your routes. Long story short, it's more or less this: place your existing routes as children underneath an empty route path in your route definition:

```typescript
const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  {
    path: '', 
    component: NavLayoutComponent, // your layout component
    children: [
      { path: 'dashboard', component: DashboardComponent },
      { path: 'detail/:id', component: HeroDetailComponent },
      { path: 'heroes', component: HeroesComponent }
    ]
  }
];
```

Then the template of the layout component will contain everything similar across the child components (e.g., titles, navigation, etc.). The `router-outlet` will load the component based on the route.

```HTML
<!--nav-layout.component.html-->
<nav>
  <a routerLink="/dashboard">Dashboard</a>
  <a routerLink="/heroes">Heroes</a>
</nav>
<router-outlet></router-outlet>
```

## Success

When dealing with many wizards in your web application, you might want the final step (after everything is completed) to be a success step with a call-to-action. You can create a `success` component with options such as:
- optional image
- title
- message
- call-to-action button text
- callback for the call-to-action button

![Success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0qry88t9o7jzvahq084q.png)

## Counter

This could be for animated purposes or an actual countdown.
You see this on many websites when they're showing numbers; they are often animated to quickly animate from 0 to the number they want to show.
Or an actual countdown, where something happens when the countdown reaches zero.

In the first case, you can create an `animated count` component. You can create the range inside your component and calculate the total duration to display from start to end. Or by using CSS only. See an explanation [here](https://css-tricks.com/animating-number-counters/).

For the actual countdown, you can create a `countdown` component in which you do the actual countdown and provide a callback when the countdown reaches zero.

## Conclusion

The types of components you need all depend on your web application, of course. The main takeaway here is to keep your component templates small, and the best way to do that is to create different components.

Do you have any more examples of possible components? Let me know in the comments.