Angular's DI can make your components smarter
Tags: javascript, angular, component, webdev
Published: 2022-04-24 15:42:59


 ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xlb0c4y0twlr4ee4hac.png)

 Angular's built in Dependency Injection is quite powerful and today we are going to see how we can use it to make our components smart(er).

Let's talk about button component
```html    
<app-button  
accent=" primary | danger | success | ... "
size =" small | medium | large | cta | ... "
icon = "[ ... ]"
iconSize = "sm | md | lg | ..."
label = "[ ... ]"
translate = " true | false "
ripple = " true | false "
tooltip = "true | false"
...
 >
</app-button>
```

Here, we can see that the button component provides different configuration option so that we could use it to cover different use cases.

Providing all these input's all the time could get cumbersome which could also lead to inconsistencies.

In order to solve this problem, we first have to find out all the places in our application where button could be placed.

for example

| Place         | Button Size | Icon Size | Show Tool Tip | Icon Only | ...
| :---          |    :----:   |    ---:   | ---:    | ---: | ---:
| App Header    | Large       | lg        | false   | false
| Card Header   | Medium      | md        | false   | false
| Table Row     | sm          | sm        | true    | true

Once we have clear idea of how and where our button is going to be used then we can create Angular's Injection Token for all the inputs where the value could be deduced from the context.

```typescript
 const BUTTON_SIZE_HINT_TOKEN = new InjectionToken<
    small | medium | large | cta | ... 
>('Button size hint token', {
    providedIn: 'root',
    factory: () => 'medium' // default value
});

 const BUTTON_ICON_HINT_TOKEN = new InjectionToken<
    lg | md | sm | hide | ... 
>('Button size hint token', {
    providedIn: 'root',
    factory: () => 'md' // default value
});

const BUTTON_TOOLTIP_HINT_TOKEN = new InjectionToken<
    boolean
>('Button size hint token', {
    providedIn: 'root',
    factory: () => false // default value
});

...
```

After creating these tokens, we have to use it in the button component.

```typescript
// button.component.ts
// ...
// ... code ommited for brevity


 constructor(
    @Inject(BUTTON_SIZE_HINT_TOKEN)
    private  buttonSize:   small | medium | large | cta | ... ,

    @Inject(BUTTON_ICON_HINT_TOKEN)
    private iconSize: lg | md | sm | hide | ...,

    @Inject(BUTTON_TOOLTIP_HINT_TOKEN)
    private showToolTip: boolean,

// ... other dependecies
    ){}
```

Here, we can use these hints to the set the default value in the button component.

The next step would be to provide these hints in the places where the button is going to be used.

```typescript 
@Component({
    selector: 'app-page-header',
    templateUrl: './template-file.html',
    providers: [
        {
            provide: BUTTON_SIZE_HINT_TOKEN,
            useValue: 'large'
        },
        {
            provide: BUTTON_ICON_HINT_TOKEN,
            useValue: 'lg'
        },
        {
            provide: BUTTON_TOOLTIP_HINT_TOKEN,
            useValue: false
        },

    ]
})
export class AppPageHeaderComponent {
```

```typescript 
@Component({
    selector: 'app-table',
    templateUrl: './template-file.html',
    providers: [
        {
            provide: BUTTON_SIZE_HINT_TOKEN,
            useValue: 'sm'
        },
        {
            provide: BUTTON_ICON_HINT_TOKEN,
            useValue: 'sm'
        },
        {
            provide: BUTTON_TOOLTIP_HINT_TOKEN,
            useValue: true
        },

    ]
})
export class TableComponent {
```

```typescript 
@Component({
    selector: 'app-card-header',
    templateUrl: './template-file.html',
    providers: [
        {
            provide: BUTTON_SIZE_HINT_TOKEN,
            useValue: 'medium'
        },
        {
            provide: BUTTON_ICON_HINT_TOKEN,
            useValue: 'md'
        },
        {
            provide: BUTTON_TOOLTIP_HINT_TOKEN,
            useValue: false
        },

    ]
})
export class AppCardHeaderComponent {
```

After doing this, we'll not have to specify buttonSize, buttonIconSize and showToolTip flag while using the app-button because the button component will get that from the context itself.

Please do let me know how you find this approach!

Thank you!