import {NgModule,Component,ElementRef,Input,Output,EventEmitter,AfterContentInit,ContentChildren,QueryList,TemplateRef,IterableDiffers,forwardRef,ViewChild} from '@angular/core'; import {CommonModule} from '@angular/common'; import {SharedModule,PrimeTemplate} from '../common/shared'; import {InputTextModule} from '../inputtext/inputtext'; import {DomHandler} from '../dom/domhandler'; import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; export const CHIPS_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Chips), multi: true }; @Component({ selector: 'p-chips', template: `
`, providers: [DomHandler,CHIPS_VALUE_ACCESSOR] }) export class Chips implements AfterContentInit,ControlValueAccessor { @Input() style: any; @Input() styleClass: string; @Input() disabled: boolean; @Output() onAdd: EventEmitter = new EventEmitter(); @Output() onRemove: EventEmitter = new EventEmitter(); @Input() field: string; @Input() placeholder: string; @Input() max: number; @Input() tabindex: number; @Input() inputId: string; @Input() allowDuplicate: boolean = true; @Input() inputStyle: any; @Input() inputStyleClass: any; @Input() addOnTab: boolean; @Input() addOnBlur: boolean; @Output() onFocus: EventEmitter = new EventEmitter(); @Output() onBlur: EventEmitter = new EventEmitter(); @ViewChild('inputtext') inputViewChild: ElementRef; @ContentChildren(PrimeTemplate) templates: QueryList; public itemTemplate: TemplateRef; value: any; onModelChange: Function = () => {}; onModelTouched: Function = () => {}; valueChanged: boolean; focus: boolean; constructor(public el: ElementRef, public domHandler: DomHandler) {} ngAfterContentInit() { this.templates.forEach((item) => { switch(item.getType()) { case 'item': this.itemTemplate = item.template; break; default: this.itemTemplate = item.template; break; } }); } onClick(event) { this.inputViewChild.nativeElement.focus(); } writeValue(value: any) : void { this.value = value; this.updateMaxedOut(); } registerOnChange(fn: Function): void { this.onModelChange = fn; } registerOnTouched(fn: Function): void { this.onModelTouched = fn; } setDisabledState(val: boolean): void { this.disabled = val; } resolveFieldData(data: any, field: string): any { if(data && field) { if(field.indexOf('.') == -1) { return data[field]; } else { let fields: string[] = field.split('.'); let value = data; for(var i = 0, len = fields.length; i < len; ++i) { value = value[fields[i]]; } return value; } } else { return null; } } onInputFocus(event: FocusEvent) { this.focus = true; this.onFocus.emit(event); } onInputBlur(event: FocusEvent) { this.focus = false; if(this.addOnBlur && this.inputViewChild.nativeElement.value) { this.addItem(event, this.inputViewChild.nativeElement.value); this.inputViewChild.nativeElement.value = ''; } this.onModelTouched(); this.onBlur.emit(event); } removeItem(event: Event, index: number): void { if(this.disabled) { return; } let removedItem = this.value[index]; this.value = this.value.filter((val, i) => i!=index); this.onModelChange(this.value); this.onRemove.emit({ originalEvent: event, value: removedItem }); this.updateMaxedOut(); } addItem(event: Event, item: string): void { this.value = this.value||[]; if(item && item.trim().length) { if(this.allowDuplicate || this.value.indexOf(item) === -1) { this.value = [...this.value, item]; this.onModelChange(this.value); this.onAdd.emit({ originalEvent: event, value: item }); } } this.updateMaxedOut(); } onKeydown(event: KeyboardEvent): void { switch(event.which) { //backspace case 8: if(this.inputViewChild.nativeElement.value.length === 0 && this.value && this.value.length > 0) { this.value = [...this.value]; let removedItem = this.value.pop(); this.onModelChange(this.value); this.onRemove.emit({ originalEvent: event, value: removedItem }); } break; //enter case 13: this.addItem(event, this.inputViewChild.nativeElement.value); this.inputViewChild.nativeElement.value = ''; event.preventDefault(); break; case 9: if(this.addOnTab && this.inputViewChild.nativeElement.value !== '') { this.addItem(event, this.inputViewChild.nativeElement.value); this.inputViewChild.nativeElement.value = ''; event.preventDefault(); } break; default: if(this.max && this.value && this.max === this.value.length) { event.preventDefault(); } break; } } updateMaxedOut() { if(this.inputViewChild && this.inputViewChild.nativeElement) { if(this.max && this.value && this.max === this.value.length) this.inputViewChild.nativeElement.disabled = true; else this.inputViewChild.nativeElement.disabled = false; } } } @NgModule({ imports: [CommonModule,InputTextModule,SharedModule], exports: [Chips,InputTextModule,SharedModule], declarations: [Chips] }) export class ChipsModule { }