ANGULAR FOR EVERYONE: PART 02

All You Need to Know About Components

When to use Angular Components & What can I do with it?

Redin Gaetan
4 min readAug 6, 2021

Okay, so previously, we have seen all about directives, and now it’s time to talk about components. Yes, I assume you have already read this article: Directives. If you don’t, I suggest you do it. Why? Not because I want more views and reads on my articles, but because we will study the component’s specific metadata in the technical part about the decorator. Why?

Because directives are the basis, and what’s simply a component? Yes, you are right. It’s an attribute directive + a template. I love how you are brilliant. Indeed, a component is no more than a subclass of a directive with some specific features.

So, do you want to create a nonexistent element or put elements together to form a global component? Here we will see how to do it.

The decorator: @Component

Thanks to this decorator, a class is recognized by Angular as a component.

All options defined for the directive are available for the component. So here, we list only the component-specific options.

changeDetection?: ChangeDetectionStrategy

I made an article about this. But to have minimal information, this is what we need to know right now:

  • The default value is ChangeDetectionStrategy.Default
  • Another strategy exists ChangeDetectionStrategy.OnPush
  • It allows defining when our component is refreshed

templateUrl?: string | template?: string

I put these two options together because you have to define one of them. However, if one is limited, you don’t need to define the other one.

Which one to choose?

If you are a purist, you should always choose the templateUrl (separation of concerns). Otherwise, you can follow the Angular style guide.

With template:

@Component({
selector: 'med-example',
template: `<span>Example</span>`,
})
export class ExampleComponent {}

With templateUrl:

// example.component.ts@Component({
selector: 'med-example',
template: './example.component.html',
})
export class ExampleComponent {}

// example.component.html
<span>Example</span>

I use both. How do I choose? If my template is a short inline template and easy to read in the ts file, I choose the template option. Otherwise, I use templateUrl. Keep in mind your code should always be easy to read/understand. That’s the key to a quality code.

styleUrls?: string[] | styles?: string[]

These two options can be used together. BUT I don’t recommend using the second one. Why?

  • First, if you use a good IDE, you will not have the autocomplete.
  • Second, global styles are challenging to maintain, so it’s better to centralize them in stylesheet files and not look for it elsewhere.

I know you are free to choose but don’t forget a big power implies big responsibilities ;-)

With styles:

@Component({
selector: 'med-example',
template: `<span>Example</span>`,
styles: ['span { width: 100%; color: red; font-weight: bold; }']
})
export class ExampleComponent {}

With styleUrls:

// example.component.ts@Component({
selector: 'med-example',
template: `<span>Example</span>`,
styles: ['./example.component.css']
})
export class ExampleComponent {}
// example.component.cssspan {
width: 100%;
color: red;
font-weight: bold;
}

Both give the same result.

animations?: any[]

I think it will be better to make its article :-) but to resume, it allows using beautiful animations.

encapsulation?: ViewEncapsulation

That’s an exciting option because we don’t have to choose once for all as a coding guideline. All values can be used in an application, and it’s not a wrong choice. It depends on the use case or the need for a component. So what are the specificities of each one?

  • ViewEncapsulation.Emulated: it’s the default value, BUT if no styleUrls or styles option is provided, it switches to ViewEncapsulation.None at compilation. The type is scoped from the host element to the descendant. TIPS: in stylesheets, if you want to style the host component, you can use the host {} selector.
  • ViewEncapsulation.None: No scope, no encapsulation. Everything is accessible and can be overridden. TIPS: if you want to style the host element use the component selector.
  • ViewEncapsulation.ShadowDom: encapsulate the component into a shadow dom. To be as simple as possible, nothing inside the shadow dom can affect anything outside it. For more information. Today, most browsers support it.

interpolation?: [string, string]

It allows overriding the default interpolation delimiters. Default is {{}}. Interpolation is what allows you to have ts code inside HTML templates.

If I can get away with advice: don’t change it. Maybe you don’t like it, and perhaps you want to use your own. BUT don’t forget you work with other developers, and most of them used the default one. So keep your code simple to read/understand.

Thanks to interpolation, we can pass typescript variables to the HTML template.

@Component({
selector: 'med-example',
template: `<span>{{text}}</span>`,
})
export class ExampleComponent {
public text: string = 'Example';
}

Preserve whitespaces?: boolean

If true, then keep all unnecessary white spaces from the compiled template. Otherwise, it will be removed, except for text inside <pre> or <textarea> because white spaces are significant.

Conclusion

You can do all the things with an attribute directive, with a component: Inputs, Outputs, HostBinding, HostListener… Just remember, if you don’t have to add a template, then prefer using a directive. No template = just behavior = attribute directive.
If you have any questions, don’t hesitate :-). Thanks for reading.

--

--