Wednesday, April 25, 2018

Angular - Display-Only Nested Components


Using the nested component

If we assume the source below is from some parent component html file it might look like this if we are showing a numeric value for the rating of a product.

{{product.startRating}}

If we then want to use a custom component (nested component) to show a nice graphical star rating instead of the numeric value we would use the syntax (property binding syntax) below assuming our component has a selector of myApp-star and has an input property called rating.

<myApp-star [rating]='product.starRating'></myApp-star>

Implementing the Nested Component

Typically nested components are kept in the shared directory of the project.
Use the component by adding it to the module as a declaration.
Input is sent from the parent component to the child (nested) component using a property on the nested component. 

star.component.ts

import { Component, OnChanges, Input } from "@angular/core";

@Component({

    selector: 'myApp-star',
    templateUrl: './star.component.html',
    styleUrls: ['./star.component.css']
})
export class StarComponent implements OnChanges {
    @Input() rating: number;

    starWidth: number;


    ngOnChanges(): void {

        this.starWidth = this.rating * 86/5;
    }
}

Passing data from parent to nested component

Notice the @Input decorator. It is required to expose a property to a parent component in the html file. The starWidth is recalculated whenever the rating property changes.

star.component.html

<div class="crop" 
    [style.width.px]="starWidth"
    [title]="rating">
    <div style="width: 86px">
        <span class="glyphicon glyphicon-star"></span>
        <span class="glyphicon glyphicon-star"></span>
        <span class="glyphicon glyphicon-star"></span>
        <span class="glyphicon glyphicon-star"></span>
        <span class="glyphicon glyphicon-star"></span>
    </div>
</div>

Notice that rating is a property in the star component and so is title

star.component.css

.crop {
    overflow: hidden;
}
div {
    cursor: pointer;
}

app module

Tell the module that contains the parent component where to find our star component be adding it to the declarations in the module. In the most basic of cases this is the app.modules.ts.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { StarComponent } from './shared/star.component';

@NgModule({
  declarations: [ AppComponent, StarComponent ],
  imports: [ BrowserModule, FormsModule ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

No comments: