Components & Databinding Deep Dive
binding to custom properties
when using *ngFor with a collection of type create a component which displays an instance of the type

the Input directive exposes the property to the template

example use is displaying a list of something with each something displayed in its own control

    ...
    @Component({
        ...
    })
    export class ServerElementComponent implements OnInit {
        @Input() element: {type: string, name: string, content: string};
        ...
    }
        
property can have public alias to be used by markup
    ...
    @Component({
        ...
    })
    export class ServerElementComponent implements OnInit {
        @Input(< public alias >) element: {type: string, name: string, content: string};
        ...
    }
        

Top

Index

binding to custom events - EventEmitter
add events initialized as type of EventEmitter to the component with arg as JSON object

import the Output directive

decorate the events with the Output directive to expose the events

note one Output property uses public aliasing

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

    @Component({
        selector: 'app-cockpit',
        ...
        })
    export class CockpitComponent implements OnInit {
        @Output('xserverCreated') serverCreated = new EventEmitter<{ serverName:=serverName string,=string, serverContent:=serverContent string=string }=}>();
        @Output() blueprintCreated = new EventEmitter<{ serverName:=serverName string,=string, serverContent:=serverContent string=string }=}>();
        ...
        onAddServer() {
            this.serverCreated.emit({ serverName: this.newServerName, serverContent: this.newServerContent });
        }
        onAddBlueprint() {
            this.blueprintCreated.emit({ serverName: this.newServerName, serverContent: this.newServerContent });    
        }
    }      
        
the parent element of this component can assign event handlers in its markup, here from app.component.html
	<app-cockpit 
		(xserverCreated)="onServerAdded($event)"
		(blueprintCreated)="onBlueprintAdded($event)">
	</app-cockpit>
        
and the handlers
    ...
    export class AppComponent {
        ...
        onServerAdded(serverData: {serverName: string, serverContent: string}) { ... }

        onBlueprintAdded(blueprintData: {serverName: string, serverContent: string})   ... }
    }   
        

Top

Index

view/style encapsulation
style sheets are only applied to their associated component

Top

Index

using local references in templates
local reference cann be placed on any HTML element

usable only in template, not in TypeScript

octothorpe denotes a local reference

    <div class="col-xs-12">
        ...
        <input type="text" class="form-control" #nameInput>
        ...
        <input type="text" class="form-control" [(ngModel)]="newServerContent">
        <br>
        <button
            class="btn btn-primary"
            (click)="onAddServer(nameInput)">Add Server</button>
        <button
            class="btn btn-primary"
            (click)="onAddBlueprint(nameInput)">Add Server Blueprint</button>
    </div>  
        
above event handler calls pass local reference as arg

handler methods are changed because they take HTMLInputElement args

    ...
    export class CockpitComponent {

        @Output('xserverCreated') serverCreated = new EventEmitter<{ serverName:=serverName string,=string, serverContent:=serverContent string=string }=}>();
        @Output() blueprintCreated = new EventEmitter<{ serverName:=serverName string,=string, serverContent:=serverContent string=string }=}>();

        newServerContent = '';

        onAddServer(nameInput: HTMLInputElement) {
            //    this.serverCreated.emit({ serverName: this.newServerName, serverContent: this.newServerContent });
            this.serverCreated.emit({ serverName: nameInput.value, serverContent: this.newServerContent });
        }

        onAddBlueprint(nameInput: HTMLInputElement) {
            //    this.blueprintCreated.emit({ serverName: this.newServerName, serverContent: this.newServerContent });    
            this.blueprintCreated.emit({ serverName: nameInput.value, serverContent: this.newServerContent });    
        }
    }
        

Top

Index

getting access to the template and DOM with @ViewChild
2-way binding is removed from the second input which receives the local reference contentInput
    <div class="col-xs-12">
        <p>Add new Servers or blueprints!</p>
        <label>Server Name</label>
        <input type="text" class="form-control" #nameInput>
		
        <label>Server Content</label>
        <input type="text" class="form-control" #contentInput >
		
        <br>
        <button 
            class="btn btn-primary" 
            (click)="onAddServer(nameInput)">Add Server</button>
        <button 
            class="btn btn-primary" 
            (click)="onAddBlueprint(nameInput)">Add Server Blueprint</button>
    </div>
        
the ViewChild directive's arg is the local reference of the desired element of the template

the element property is assigned the reference

    import { Component, OnInit, EventEmitter, Output, ViewChild, ElementRef } from '@angular/core';
    ...
    export class CockpitComponent implements OnInit {
        ...
        @ViewChild('contentInput') contentInput: ElementRef;
        ...

        onAddServer(nameInput: HTMLInputElement) {
            this.serverCreated.emit({ serverName: nameInput.value, serverContent: this.contentInput.nativeElement.value });
        }

        onAddBlueprint(nameInput: HTMLInputElement) { 
            this.blueprintCreated.emit({ serverName: nameInput.value, serverContent: this.contentInput.nativeElement.value });
        }
    }    
        

Top

Index

projecting content into component using ng-Content
everything between a component's selectors is lost
    <some-component>    
        This text will never be rendered...    
    </some-component>        
        
if the ng-Content directive is used in the SomeComponent markup
    <div>
        <ng-Content></ng-Content>
        This is the SomeComponent
    </div>
        
any content found between the opening and closing tags of some-component will be shown between the ng-Content tags

the output will be

    This text will never be rendered...
    This is the SomeComponent
        

Top

Index

lifecycle hooks
ngInit is a lifecycle hook

lifecycle hooks

Top

Index

lifecycle hooks and template access
AfterViewInit DOM elements can be accessed

Top

Index

n4jvp.com