19 June 2019
Angular (6) -- Data Binding
by Jerry Zhang
Day 15:
package.json file
The dependencies used in production environment are listed in the dependencies
attribute, whereas the ones used in
development environment are listed in the devDependencies
attribute.
Some commonly used npm commands:
Install dependencies:
npm i --save <dependency name>
or
npm i --save-dev <dependency name>
Create a new project:
ng new
Build in production environment:
ng build -prod
Start the server:
ng serve
Mock Rest API tool: json-server
npm install -g json-server
Create a json file first. Then import it with json server.
json-server ./mock/data.json
Passing data between components
Custom property binding
In the child component, we can define an input property in the typescript file.
@Input() element: {type: string, name: string, content: string};
This property element
of course can be used in the current HTML file, but more important, by adding @Input
, we
can pass in an element
from outside. The data source is stored in the parent component. In the parent HTML file, we
can define a property called ‘element’ in the
serverElements = [{type: 'server', name: 'TestServer', content: 'A test'}];
<app-server-element
*ngFor="let serverElement of serverElements"
[element] = "serverElement"></app-server-element>
Then we can use this element in our child component.
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<p>
<strong *ngIf="element.type === 'server'" style="color: red"></strong>
<em *ngIf="element.type === 'blueprint'" style="color: blue"></em>
</p>
</div>
</div>
Binding custom event
An event will transport data in the other direction. It starts from a child component, for example, an input. This input value will be firstly saved in its own typescript file as an attribute. To pass out this value, we firstly need to define a EventEmitter an @Output on it.
@Output() serverCreated = new EventEmitter<{serverName: string, serverContent: string}>();
@Output() blueprintCreated = new EventEmitter<{serverName: string, serverContent: string}>();
These two objects can be used to emit an event when we click a button. For example, in the html file we define a button with an event click.
<button
class="btn btn-primary"
(click)="onAddServer()">Add Server</button>
<button
class="btn btn-primary"
(click)="onAddBlueprint()">Add Server Blueprint</button>
Then in the typescript file, we define these two methods.
onAddServer() {
this.serverCreated.emit({serverName: this.newServerName, serverContent: this.newServerContent});
}
onAddBlueprint() {
this.blueprintCreated.emit({serverName: this.newServerName, serverContent: this.newServerContent});
}
In these two methods, we will use the two EventEmitter objects, serverCreated and blueprintCreated, that we defined in the first step, and emit an event with some data in JSON format.
Now, in the parent component, we can receive an event in the
<app-cockpit
(serverCreated)="onServerAdded($event)"
(blueprintCreated)="onBlueprintAdded($event)"
></app-cockpit>
The final step is to define the corresponding methods in the parent component.
onServerAdded(serverData: {serverName: string, serverContent: string}) {
this.serverElements.push({
type: 'server',
name: serverData.serverName,
content: serverData.serverContent
});
}
onBlueprintAdded(blueprintData: {serverName: string, serverContent: string}) {
this.serverElements.push({
type: 'blueprint',
name: blueprintData.serverName,
content: blueprintData.serverContent
});
}
CSS is different in Angular
Generally, css is applied in all the html documents. However, in Angular, css only get applied in its own component.
Every element in Angular has an additional attribute added by Angular at runtime. It simulates shadow DOM.
Overwrite the view encapsulation
In a component, if we write encapsulation: ViewEncapsulation.None
, the css will apply globally.
Local references
Add a #
in the input element.
<input
type="text"
class="form-control"
#serverNameInput>
Then we can refer it in the same html file.
<button
class="btn btn-primary"
(click)="onAddServer(serverNameInput)">Add Server</button>
<button
class="btn btn-primary"
(click)="onAddBlueprint(serverNameInput)">Add Server Blueprint</button>
Then we can use it in the ts file.
onAddServer(serverNameInput: HTMLInputElement) {
this.serverCreated.emit({
serverName: serverNameInput.value,
serverContent: this.newServerContent
});
}
onAddBlueprint(serverNameInput: HTMLInputElement) {
this.blueprintCreated.emit({
serverName: serverNameInput.value,
serverContent: this.newServerContent
});
}
Getting access to the template and DOM with @ViewChild
We can also access the DOM with @ViewChild.
<input
type="text"
class="form-control"
#serverContentInput>
@ViewChild('serverContentInput', { static: true }) serverContentInput: ElementRef;
onAddServer(serverNameInput: HTMLInputElement) {
this.serverCreated.emit({
serverName: serverNameInput.value,
serverContent: this.serverContentInput.nativeElement.value
});
}
Putting content inside custom tags
By default, everything between
We can put something inside custom components, but we need to put <ng-content></ng-content>
in the same place as a
hook.
Lifecycle
- ngOnChanges
- ngOnInit
- ngDoCheck
- ngAfterContentInit
- ngAfterContentChecked
- ngAfterViewInit
- ngAfterViewChecked
- ngOnDestroy