Build a Reusable Button Component with Angular

Build a Reusable Button Component with Angular

Build a Reusable Button Component with Angular.We have seen how to build a reusable component that can be used in many different situations. Obviously, this here is a simplified case, but it shows the approach a developer should use for this kind of challenge really well.

One of the first concerns of a good web developer is writing clean code and avoiding repetition. This strategy becomes a necessity when developing large, scalable applications that could be expanded with new features in the future.

Reusable components can make the difference between a successful project and one with high technical debt.

In this article, we will build together a reusable, customizable button component that will be able to display text buttons or image buttons according to the provided configuration.

Step 1. Base Structure

First of all, when thinking about the structure of a reusable component, we need to take into consideration all the uses we want to make of it.

In the case of a reusable button, we want to create a presentational (or dumb) component that will receive the correct configuration from its parent component.

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

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.scss']
})
export class ButtonComponent implements OnInit {
  @Input() buttonConfig: any;
  constructor() {}

  ngOnInit() {}
}

button.component.ts

The object buttonConfigwill contain the styling and additional information about which kind of button we want to render: if we want a text button, the buttonConfigwill contain a textproperty; otherwise, if we want to render an image button, the configurations will specify an image source.

The HTML code will contain two different templates, one for text buttons and one for the image buttons.

Using the ngTemplateOutletpattern, we can specify when to render each one.

In this case, if the configurations contain the textproperty, the #text template will be rendered; if there’s no text property, the rendered template will be#image.

<ng-container *ngTemplateOutlet="buttonConfig['text'] ? text : image">
</ng-container>

<!-- Text Button -->
<ng-template #text>

</ng-template>

<!-- Image Button -->
<ng-template #image>

</ng-template

button.component.html

Step 2. Buttons Markup

Now that the templates are ready, we can fill them with the code for the buttons.

As you can see, the text button will display the property buttonConfig.text through interpolation. The image button is just a clickable image that will have the property buttonConfig.srcas its image source.

<ng-container *ngTemplateOutlet="buttonConfig['text'] ? text : image">
</ng-container>

<!-- Text Button -->
<ng-template #text>
  <button type="button"
          [ngStyle]="buttonConfig.styles"
          (click)="onTextBtnClick()">
    {{ buttonConfig.text | uppercase}}
  </button>
</ng-template>

<!-- Image Button -->
<ng-template #image>
  <img alt="image button"
       [src]="buttonConfig.src"
       [ngStyle]="buttonConfig.styles"
       (click)="onImgBtnClick()">
</ng-template>

button.component.html

Step 3. Configuration

With the button component ready to receive its configuration as input, we can define our custom styles in the parent component.

In this case, I have chosen to create a textBtnConfigobject and an imgBtnConfig to show you how I’ll use the button component to render two different instances at the same time and with different configurations.

It’s important to notice that since we are declaring the CSS styling in a TypeScript object, we’ll need to use the camelCase format when naming the properties! Hence ‘background-color’becomes ‘backgroundColor’, etc.

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  message = 'Click on a button';
  textBtnConfig = {
    styles: {
      position: 'relative',
      width: '150px',
      height: '60px',
      backgroundColor: '#f92672',
      color: '#fff',
      fontFamily: 'sans-serif',
      fontSize: '20px',
      borderRadius: '10px',
      marginTop: '30px'
    },
    text: 'Click Here'
  };

  imgBtnConfig = {
    styles: {
      position: 'relative',
      width: '100px',
      height: '100px'
    },
    src: './assets/conversation.png'
  };

  onClickEventReceived(event: string) {
    this.message = event;
  }
}

app.component.ts

Step 4. Rendering

Finally, we can use the button component to instantiate two buttons in the parent component:

<section>
  <h1>DIFFERENT BUTTONS, SAME COMPONENT!</h1>
  <span>{{message}}</span>
  <div class="btns-container">
    <app-button [buttonConfig]="textBtnConfig"
                (textBtnClickEmt)="onClickEventReceived($event)"></app-button>
    <app-button [buttonConfig]="imgBtnConfig"
                (imgBtnClickEmt)="onClickEventReceived($event)"></app-button>
  </div>
  <div class="copyright">
    <span>Code by Alessia Amitrano.</span>
    <span>
      Icons made by <a href="https://www.flaticon.com/authors/freepik"
         title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/"
         title="Flaticon">www.flaticon.com</a></span>
  </div>
</section>

app.component.html

Once the app is served, the result will be similar to this:

This is image title

Conclusion

We have seen how to build a reusable component that can be used in many different situations. Obviously, this here is a simplified case, but it shows the approach a developer should use for this kind of challenge really well.

Just think about how much code we would have written without a reusable component!

Moreover, reusable components allow implementing new features for every instance of the component with the minimum amount of changes to the code. If we wanted to add a new method, it would be available for every button, no matter if it’s a text or an image button.

You can find the full example implemented by me in this GitHub Repo.

Icons made by Freepik from www.flaticon.com

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

Brave, Chrome, Firefox, Opera or Edge: Which is Better and Faster?

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

15 Common Mistakes Developers Made While writing JavaScript Apps

Every developer make mistake some time when writing apps. This is a normal part of the development process. In this post, we'll learn 15 Common Mistakes Developers Made While Writing JavaScript Apps hope this post will help you

An Angular Roadmap — The Past, Present, and Future of Angular

✅Interested in being an Angular developer in 2019? ... blog post it's most likely that you've written some code in javaScript in the past.