20
loading...
This website collects cookies to deliver better user experience
<app-tags [tags]="tags" (tagsChange)="tags = $event"></app-tags>
<app-tags [(ngModel)]="tags" [disabled]="…"></app-tags>
<app-tags [ngModel]="tags" (ngModelChange)="myCallback($event)"></app-tags>
<app-tags [formControl]="tagsControl"></app-tags>
<app-tags formControlName="tags"></app-tags>
<ul>
<ng-template ngFor [ngForOf]="tags" let-tag let-index="index">
<li>
{{tag}}
<button type="button" (click)="remove(index)">x</button>
</li>
</ng-template>
</ul>
<input type="text"
[(ngModel)]="newTag"
(keydown)="onInputKeyDown($event)"
placeholder="type some text and press Enter" />
export class TagsComponent implements OnChanges {
@Input() tags: string[];
@Output() tagsChange = new EventEmitter<string[]>();
newTag = '';
constructor() { }
ngOnChanges() {
this.tags = this.tags || [];
}
remove(index: number) {
this.tags.splice(index, 1);
this.copyAndEmit();
}
onInputKeyDown($event: KeyboardEvent) {
if ($event.key === 'Enter') {
this.tags.push(this.newTag);
this.copyAndEmit();
this.newTag = '';
} else if ($event.key === 'Backspace' && this.newTag === '') {
this.tags.pop();
this.copyAndEmit();
}
}
private copyAndEmit() {
this.tags = this.tags.slice(0);
this.tagsChange.emit(this.tags);
}
}
<app-tags [tags]="tags" (tagsChange)="tags = $event"></app-tags>
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
…
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TagsComponent),
multi: true
}]
}) export class TagsComponent {
…
}
setDisabled
method. Angular will use this method to enable or disable your component.export class TagsComponent implements ControlValueAccessor {
onChange: (value: string[]) => void = () => {};
onTouched: Function = () => {};
isDisabled = false;
…
writeValue(value: string[]) {
this.tags = value || [];
}
registerOnChange(fn: any) {
this.onChange = fn;
}
registerOnTouched(fn: any) {
this.onTouched = fn;
}
setDisabledState(disabled: boolean) {
this.isDisabled = disabled;
}
}
import { Component, forwardRef, HostBinding } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-tags',
templateUrl: './tags.component.html',
styleUrls: ['./tags.component.sass'],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TagsComponent),
multi: true
}]
})
export class TagsComponent implements ControlValueAccessor {
// tags is no longer an input of our component, we have writeValue to handle that logic now
tags: string[] = [];
newTag = '';
// we give some disabled style
@HostBinding('class.disabled')
isDisabled = false;
// we store the two callbacks that Angular gives us
// we also provide defaults so that our component can be used standalone
onChange: (value: string[]) => void = () => {};
onTouched: Function = () => {};
constructor() { }
// didn't change!
remove(index: number) {
this.tags.splice(index, 1);
this.copyAndEmit();
}
// didn't change!
onInputKeyDown($event: KeyboardEvent) {
if ($event.key === 'Enter') {
this.tags.push(this.newTag);
this.newTag = '';
this.copyAndEmit();
} else if ($event.key === 'Backspace' && this.newTag === '') {
this.tags.pop();
this.copyAndEmit();
}
}
// writeValue is called by Angular when the input value changes
writeValue(value: string[]) {
this.tags = value || [];
}
// registerOnChange is called by Angular
// this is the opportunity for us to save the onChange callback
// we use this callback to "output" new values
registerOnChange(fn: any) {
this.onChange = fn;
}
// registerOnTouched is called by Angular
// this is the opportunity for us to save the onTouched callback
// we use this callback to notify Angular when our component has been touched
registerOnTouched(fn: any) {
this.onTouched = fn;
}
// setDisabledState is called by Angular
// this is the opportunity for us to adjust our component style and logic
setDisabledState(disabled: boolean) {
this.isDisabled = disabled;
}
// we remove the @Output that we had and we, instead, emit through the onChange callback
// we also tell Angular that the component has been touched
private copyAndEmit() {
this.tags = this.tags.slice(0);
this.onChange(this.tags);
this.onTouched();
}
}
ngModel
.