Added Tag Input

This commit is contained in:
Caesar2011
2017-05-18 00:09:41 +02:00
parent 05e0c1ff3d
commit 01205b16b9
9 changed files with 261 additions and 170 deletions

View File

@@ -1,6 +1,18 @@
<form #form="ngForm">
<counter-input [(ngModel)]="result" name="res"></counter-input>
<form #formCounter="ngForm">
<counter-input [(ngModel)]="resultCounter" name="res"></counter-input>
</form>
<p>Value:</p>
<pre>{{ result }}</pre>
<pre>{{ resultCounter }}</pre>
<hr>
<form #formTag="ngForm">
<tag-input [(ngModel)]="resultTag" name="res" [id]="'a'" [items]="{'alpha': 'A', 'beta': 'B', 'gamma': 'G'}"></tag-input>
<tag-input [(ngModel)]="resultTag2" name="res2" [id]="'b'" [items]="{'alpha': 'A', 'beta': 'B', 'gamma': 'G'}" [nullable]="true"></tag-input>
</form>
<p>Value:</p>
<pre>{{ resultTag | json }}</pre>
<pre>{{ resultTag2 | json }}</pre>

View File

@@ -6,5 +6,7 @@ import { Component } from '@angular/core';
})
export class AppComponent {
public result = 10;
public resultCounter = 10;
public resultTag = {"alpha": true, "beta": false};
public resultTag2 = {"alpha": true, "beta": false};
}

View File

@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import {JsonInputModule} from "./counter-input.module";
import {CustomInputModule} from "./custom-input.module";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
@NgModule({
@@ -10,7 +10,7 @@ import {FormsModule, ReactiveFormsModule} from "@angular/forms";
BrowserModule,
FormsModule,
ReactiveFormsModule,
JsonInputModule,
CustomInputModule,
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]

View File

@@ -45,6 +45,11 @@ export class CounterInputComponent extends CustomInputComponent {
this.value = this.value + number;
this.parseError = isNaN(this.value);
super.onChange(number);
super.change();
}
// on touched
protected onBlur(): void {
super.blur();
}
}

View File

@@ -1,7 +1,7 @@
import {ControlValueAccessor, FormControl, ValidationErrors, Validator} from '@angular/forms';
export abstract class CustomInputComponent implements ControlValueAccessor, Validator {
protected value: number;
protected value: any;
protected parseError: boolean;
private propagateChange: (_: any) => void = () => {};
private propagateTouch: () => void = () => {};
@@ -23,12 +23,12 @@ export abstract class CustomInputComponent implements ControlValueAccessor, Vali
public abstract validate(c: FormControl): ValidationErrors;
// on change
protected onChange(value: any): void {
protected change(): void {
this.propagateChange(this.value);
}
// on touch
protected onBlur(): void {
protected blur(): void {
this.propagateTouch();
}
}

View File

@@ -2,6 +2,7 @@ import {FormsModule} from '@angular/forms';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { CounterInputComponent } from './counter-input.component';
import {KeysPipe, TagInputComponent} from './tag-input.component';
@NgModule({
@@ -11,10 +12,13 @@ import { CounterInputComponent } from './counter-input.component';
],
exports: [
CounterInputComponent,
TagInputComponent,
],
declarations: [
CounterInputComponent,
TagInputComponent,
KeysPipe
],
providers: [],
})
export class JsonInputModule { }
export class CustomInputModule { }

View File

@@ -0,0 +1,88 @@
import {Component, forwardRef, Input, Pipe, PipeTransform} from '@angular/core';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl, ValidationErrors } from '@angular/forms';
import {CustomInputComponent} from "./custom-input.component";
@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value: Object, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]});
}
return keys;
}
}
@Component({
selector: 'tag-input',
template:
`
<div *ngFor="let entry of value | keys" (click)="onChange(entry.key, true)" (contextmenu)="onChange(entry.key, false)">
{{items[entry.key]}}: {{entry.value}}
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TagInputComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => TagInputComponent),
multi: true,
}]
})
export class TagInputComponent extends CustomInputComponent {
@Input() items: Array<{key: string, value: string}> = [];
@Input() nullable: boolean = false;
@Input() id: string = "";
// set initial value
public writeValue(obj: any): void {
let isUpdated = false;
this.value = {};
if (!obj) {
obj = {};
}
for (let key in this.items) {
if (this.items.hasOwnProperty(key)) {
if (obj.hasOwnProperty(key) && (typeof(obj[key]) === "boolean" || (this.nullable && null===obj[key])))
this.value[key] = obj[key];
else {
isUpdated = true;
this.value[key] = (this.nullable ? null : false);
}
}
}
console.log(this.id, isUpdated, this.value);
if (isUpdated) {
super.change();
}
}
// validates the form, returns null when valid else the validation object
public validate(c: FormControl): ValidationErrors {
return null;
}
// on button click
protected onChange(key: string, forward: boolean): boolean {
let value = this.value[key];
if (!this.nullable)
value = !value;
else if (value===null)
value = forward;
else if ((value ? !forward : forward))
value = null;
else
value = !value;
this.value = Object.assign({}, this.value);
this.value[key] = value;
super.change();
return false;
}
}