Angular 7: Advanced Components

Throughout this book, we’ve learned how to use Angular’s built-in directives and how to create components of our own. In this chapter we’ll take a deep dive into advanced features we can use to make components.

In this chapter we’ll learn the following concepts:

How to Use This Chapter

This chapter gives a tour of advanced Angular APIs. It’s assumed the reader is familiar with the basics of creating components, using built-in directives, and organizing component files.

As this is an intermediate/advanced level chapter, it’s assumed the reader is able to fill in some of the basics (such as importing dependencies).

This chapter comes with runnable code, found in the advanced-components folder. If at any time you feel you’re lacking context, checkout the example code for this chapter.

To run the demos in this chapter, change into the project folder and run:

npm install
npm start

Then open your browser to http://localhost:4200

Styling

Angular provides a mechanism for specifying component-specific styles. CSS stands for cascading style sheet, but sometimes we don’t want the cascade. Instead we want to provide styles for a component that won’t leak out into the rest of our page.

Angular provides two attributes that allow us to define CSS classes for our component.

To define the style for our component, we use the View attribute styles to define in-line styles, or styleUrls, to use external CSS files. We can also declare those attributes directly on the Component decorator.

Let’s write a component that uses inline styles:

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-inline-style',
      styles: [`
      .highlight {
        border: 2px solid red;
        background-color: yellow;
        text-align: center;
        margin-bottom: 20px;
      }
      `],
      template: `
      <h4 class="ui horizontal divider header">
        Inline style example
      </h4>
    
      <div class="highlight">
        This uses component <code>styles</code>
        property
      </div>
      `
    })
    export class InlineStyleComponent {
    }

In this example we defined the styles we want to use by declaring the .highlight class as an item on the array on the styles parameter.

Further on in the template we reference that class on the div using <div class="highlight">.

And the result is exactly what we expect - a div with a red border and yellow background:

logo

Another way to declare CSS classes is to use the styleUrls property. This allows us to declare our CSS in an external file and just reference them from the component.

Let’s write another component that uses this, but first let’s create a file called external.css with the following class:

    .highlight {
      border: 2px dotted red;
      text-align: center;
      margin-bottom: 20px;
    }

Then we can write the code that references it:

    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-external-style',
      styleUrls: ['./external-style.component.css'],
      template: `
    <h4 class="ui horizontal divider header">
      External style example
    </h4>
    
    <div class="highlight">
      This uses component <code>styleUrls</code>
      property
    </div>
    `
    })
    export class ExternalStyleComponent {
    }

And when we load the page, we see our div with a dotted border:

logo

View (Style) Encapsulation

One interesting thing about this example is that both components define a class called highlight with different properties, but the attributes of one didn’t leak into the other.

This happens because Angular styles are encapsulated by the component context by default. If we inspect the page and expand the <head>, we’ll notice that Angular injected a <style> tag with our style:

logo

You’ll also notice that the CSS class has been scoped with _ngcontent-hve-2:

.highlight[\_ngcontent-hve-2] {
  border: 2px solid red;
  background-color: yellow;
  text-align: center;
  margin-bottom: 20px;
}

And if we check how our <div> is rendered, you’ll find that _ng-content-hve-2 was added:

logo

The same thing happens for our external style:

logo

and:

logo

Angular allows us to change this behavior, by using the encapsulation property.

This property can have the following values, defined by the ViewEncapsulation enum:

Shadow DOM Encapsulation

You might be wondering: what is the point of using the Shadow DOM? By using the Shadow DOM the component uses a unique DOM tree that is hidden from the other elements on the page. This allows styles defined within that element to be invisible to the rest of the page.

For a deep dive into Shadow DOM, please check this guide by Eric Bidelman.

Let’s create another component that uses the Native encapsulation (Shadow DOM) to understand how this works:

```javascript) import { Component, ViewEncapsulation } from ‘@angular/core’;

  @Component({
  selector: 'app-native-encapsulation',
  styles: [`
  .highlight {
    text-align: center;
    border: 2px solid black;
    border-radius: 3px;
    margin-botton: 20px;
  }`],
  template: `
  <h4 class="ui horizontal divider header">
    Native encapsulation example
  </h4>

  <div class="highlight">
    This component uses <code>ViewEncapsulation.Native</code>
  </div>
  `,
  encapsulation: ViewEncapsulation.Native
})
export class NativeEncapsulationComponent {
} ```

In this case, if we inspect the source code, we’ll see:

logo

Everything inside the #shadow-root element has been encapsulated and isolated from the rest of the page.

No Encapsulation

Finally, if we create a component that specifies ViewEncapsulation.None, no style encapsulation will be added:

    import {
      Component,
      ViewEncapsulation
    } from '@angular/core';
    
    @Component({
      selector: 'app-no-encapsulation',
      styles: [`
      .highlight {
        border: 2px dashed red;
        text-align: center;
        margin-bottom: 20px;
      }
      `],
      template: `
      <h4 class="ui horizontal divider header">
        No encapsulation example
      </h4>
    
      <div class="highlight">
        This component uses <code>ViewEncapsulation.None</code>
      </div>
      `,
      encapsulation: ViewEncapsulation.None
    })
    export class NoEncapsulationComponent {
    }
 
This page is a preview of ng-book 2.
Get the rest of this chapter plus hundreds of pages Angular 7 instruction, 5 sample projects, a screencast, and more.

 

Ready to master Angular 7?

  • What if you could master the entire framework – with solid foundations – in less time without beating your head against a wall? Imagine how quickly you could work if you knew the best practices and the best tools?
  • Stop wasting your time searching and have everything you need to be productive in one, well-organized place, with complete examples to get your project up without needing to resort to endless hours of research.
  • You will learn what you need to know to work professionally with ng-book: The Complete Book on Angular 7 or get your money back.
Download the First Chapter (for free)