File

src/app/shared/components/tag-input/tag-input.component.ts

Implements

OnInit OnChanges

Metadata

selector crm-tag-input
styleUrls tag-input.component.scss
templateUrl ./tag-input.component.html

Index

Properties
Methods
Inputs
Outputs
HostBindings

Inputs

addOnBlur

Type: boolean

Default value: true

addOnEnter

Type: boolean

Default value: true

addOnPaste

Type: boolean

Default value: true

allowedTagsPattern

Type: RegExp

Default value: /.+/

delimiterCode

Type: number

Default value: 32

errorMessage

Default value: "Invalid email"

items

Type: string[]

Default value: []

pasteDelimiter

Type: RegExp

Default value: null

placeholder

Type: string

Default value: 'Add a tag'

readonly

Type: boolean

Default value: false

Outputs

itemsChange $event type: EventEmitter

HostBindings

class.crm-tag-input-focus
class.crm-tag-input-focus:

Methods

Private _addTags
_addTags(tags: string[])
Parameters :
Name Type Optional Description
tags string[]
Returns : void
Private _handleBackspace
_handleBackspace()
Returns : void
Private _isTagValid
_isTagValid(tagString: string)
Parameters :
Name Type Optional Description
tagString string
Returns : any
Private _removeTag
_removeTag(tagIndexToRemove: )
Parameters :
Name Type Optional Description
tagIndexToRemove
Returns : void
Private _resetInput
_resetInput()
Returns : void
Private _resetSelected
_resetSelected()
Returns : void
Private _splitString
_splitString(tagString: string)
Parameters :
Name Type Optional Description
tagString string
Returns : any
inputBlurred
inputBlurred(event: )
Parameters :
Name Type Optional Description
event
Returns : void
inputChanged
inputChanged(event: )
Parameters :
Name Type Optional Description
event
Returns : void
inputFocused
inputFocused(event: )
Parameters :
Name Type Optional Description
event
Returns : void
inputPaste
inputPaste(event: )
Parameters :
Name Type Optional Description
event
Returns : void
isBlank
isBlank(obj: any)
Parameters :
Name Type Optional Description
obj any
Returns : boolean
isValid
isValid()
Returns : boolean
Private isValidAndNotInTagList
isValidAndNotInTagList(tagString: string)
Parameters :
Name Type Optional Description
tagString string
Returns : boolean
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional Description
changes SimpleChanges
Returns : void
ngOnInit
ngOnInit()
Returns : void
registerOnChange
registerOnChange(fn: any)
Parameters :
Name Type Optional Description
fn any
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Parameters :
Name Type Optional Description
fn any
Returns : void
Private splitPasteString
splitPasteString(tagString: string)
Parameters :
Name Type Optional Description
tagString string
Returns : any
Private uniqueTags
uniqueTags(tags: string[])
Parameters :
Name Type Optional Description
tags string[]
Returns : any
writeValue
writeValue(value: any)
Parameters :
Name Type Optional Description
value any
Returns : void

Properties

Public delimiter
delimiter: number
Type : number
Public inputValue
inputValue: string
Type : string
Default value : ''
onChange
onChange: function
Type : function
Default value : () => { this.itemsChange.emit(this.tagsList); }

Implemented as part of ControlValueAccessor.

onTouched
onTouched: function
Type : function
Default value : () => { }
Public selectedTag
selectedTag: number
Type : number
Public tagsList
tagsList: string[]
Type : string[]
import {Component, Input, HostBinding, Output, EventEmitter, OnInit, OnChanges, SimpleChanges} from "@angular/core";

@Component({
  selector: 'crm-tag-input',
  templateUrl: './tag-input.component.html',
  styleUrls: ['./tag-input.component.scss']
})
export class TagInputComponent implements OnInit, OnChanges {

  @Input() placeholder: string = 'Add a tag';
  @Input() items: string[] = [];
  @Output() itemsChange = new EventEmitter<string[]>();
  @Input() delimiterCode: number = 32;
  @Input() pasteDelimiter: RegExp = null;
  @Input() addOnBlur: boolean = true;
  @Input() addOnEnter: boolean = true;
  @Input() addOnPaste: boolean = true;
  @Input() allowedTagsPattern: RegExp = /.+/;
  @Input() errorMessage = "Invalid email";
  @HostBinding('class.crm-tag-input-focus') isFocussed;
  @Input() readonly: boolean = false;

  public tagsList: string[];
  public inputValue: string = '';
  public delimiter: number;
  public selectedTag: number;

  ngOnInit() {
    this.tagsList = this.items;
    this.onChange(this.tagsList);
    this.delimiter = this.delimiterCode;
  }

  ngOnChanges(changes: SimpleChanges) {
    if(changes['items']) {
      this.tagsList = this.items
    }
  }

  ngAfterViewInit() {
    // If the user passes an undefined variable to items this will warn
    // and set the value to an empty array
    if (!this.tagsList) {
      console.warn('TagInputComponent was passed an undefined value in items. Please make sure the variable is defined.');
      this.tagsList = [];
      this.onChange(this.tagsList);
    }
  }

  inputChanged(event) {
    let key = event.keyCode;
    switch (key) {
      case 8: // Backspace
        this._handleBackspace();
        break;
      case 13: //Enter
        this.addOnEnter && this._addTags([this.inputValue]);
        event.preventDefault();
        break;

      case this.delimiter:
        this._addTags([this.inputValue]);
        event.preventDefault();
        break;

      default:
        this._resetSelected();
        break;
    }
  }

  inputBlurred(event) {
    this.addOnBlur && this._addTags([this.inputValue]);
    this.isFocussed = false;
  }

  inputFocused(event) {
    this.isFocussed = true;
  }

  inputPaste(event) {
    let clipboardData = event.clipboardData || (event.originalEvent && event.originalEvent.clipboardData);
    let pastedString = clipboardData.getData('text/plain');
    let tags = this.splitPasteString(pastedString);
    let tagsToAdd = tags.filter((tag) => this.isValidAndNotInTagList(tag));
    let filteredTagsToAdd = this.uniqueTags(tagsToAdd);
    this._addTags(filteredTagsToAdd);
    setTimeout(() => this.inputValue = '', 50);
  }

  private _splitString(tagString: string) {
    tagString = tagString.trim();
    let tags = tagString.split(String.fromCharCode(this.delimiter));
    return tags.filter((tag) => !!tag);
  }

  private splitPasteString(tagString: string) {
    tagString = tagString.trim();
    let tags = this.pasteDelimiter ? tagString.split(this.pasteDelimiter) : tagString.split(/\s\n|\n\s|\s|\n/);
    return tags.filter((tag) => !!tag.trim());
  }

  private _isTagValid(tagString: string) {
    return this.allowedTagsPattern.test(tagString);
  }

  private isValidAndNotInTagList(tagString: string) {
    return this.allowedTagsPattern.test(tagString) && !this.tagsList.find(tag => tag === tagString);
  }

  private uniqueTags(tags: string[]) {
    return tags.filter((tag, index, array) => index == array.indexOf(tag));
  }

  private _addTags(tags: string[]) {
    let validTags = tags.filter((tag) => this._isTagValid(tag));
    this.tagsList = this.tagsList.concat(validTags);
    this._resetSelected();
    this._resetInput();
    this.onChange(this.tagsList);
  }

  private _removeTag(tagIndexToRemove) {
    this.tagsList.splice(tagIndexToRemove, 1);
    this._resetSelected();
    this.onChange(this.tagsList);
  }

  private _handleBackspace() {
    if (!this.inputValue.length && this.tagsList.length) {
      if (!this.isBlank(this.selectedTag)) {
        this._removeTag(this.selectedTag);
      }
      else {
        this.selectedTag = this.tagsList.length - 1;
      }
    }
  }

  private _resetSelected() {
    this.selectedTag = null;
  }

  private _resetInput() {
    this.inputValue = '';
  }

  /** Implemented as part of ControlValueAccessor. */
  onChange: (value) => any = () => {
    this.itemsChange.emit(this.tagsList);
  };

  onTouched: () => any = () => {
  };

  writeValue(value: any) {
  }

  registerOnChange(fn: any) {
    this.onChange = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouched = fn;
  }

  isValid() {
    return this.inputValue && !this._isTagValid(this.inputValue);
  }

  isBlank(obj: any): boolean {
    return obj == null;
  }

}
<crm-tag-input-item
  [text]="tag"
  [index]="index"
  [selected]="selectedTag === index"
  (tagRemoved)="_removeTag($event)"
  [readonly]="readonly"
  *ngFor="let tag of tagsList; let index = index">
</crm-tag-input-item>

<input
  class="form-control"
  type="text"
  autocomplete="off"
  [placeholder]="placeholder"
  [(ngModel)]="inputValue"
  (paste)="inputPaste($event)"
  (keydown)="inputChanged($event)"
  (blur)="inputBlurred($event)"
  (focus)="inputFocused()"
  *ngIf="!readonly">

<div class="form-error" *ngIf="isValid()">
  {{errorMessage}}
</div>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""