UNPKG

smart-webcomponents

Version:

Web Components & Custom Elements for Professional Web Applications

531 lines (456 loc) 18.3 kB
import { PhoneInput } from './../index'; import { DropDownButtonPosition, ElementRenderMode} from './../index'; import { Component, Directive, AfterViewInit, ElementRef, Input, OnInit, OnChanges, OnDestroy, SimpleChanges, forwardRef, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; import { BaseElement, Smart } from './smart.element'; export { DropDownButtonPosition, ElementRenderMode} from './../index'; export { Smart } from './smart.element'; export { PhoneInput } from './../index'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PhoneInputComponent), multi: true } @Directive({ exportAs: 'smart-phone-input', selector: 'smart-phone-input, [smart-phone-input]', providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] }) export class PhoneInputComponent extends BaseElement implements OnInit, AfterViewInit, OnDestroy, OnChanges, ControlValueAccessor { constructor(ref: ElementRef<PhoneInput>) { super(ref); this.nativeElement = ref.nativeElement as PhoneInput; } private eventHandlers: any[] = []; public declare nativeElement: PhoneInput; /** @description Creates the component on demand. * @param properties An optional object of properties, which will be added to the template binded ones. */ public createComponent(properties = {}): any { this.nativeElement = <PhoneInput>document.createElement('smart-phone-input'); for (let propertyName in properties) { this.nativeElement[propertyName] = properties[propertyName]; } return this.nativeElement; } /** * @description * The registered callback function called when a change event occurs on the form elements. */ _onChange: (value: any) => void = () => {}; /** * @description * The registered callback function called when a blur event occurs on the form elements. */ _onTouched: () => any = () => {}; /** @description Enables or disables the element. */ @Input() get disabled(): boolean { return this.nativeElement ? this.nativeElement.disabled : undefined; } set disabled(value: boolean) { this.nativeElement ? this.nativeElement.disabled = value : undefined; } /** @description Sets additional class names to the Input drop down. */ @Input() get dropDownClassList(): any { return this.nativeElement ? this.nativeElement.dropDownClassList : undefined; } set dropDownClassList(value: any) { this.nativeElement ? this.nativeElement.dropDownClassList = value : undefined; } /** @description Determines the position of the drop down button. */ @Input() get dropDownButtonPosition(): DropDownButtonPosition | string { return this.nativeElement ? this.nativeElement.dropDownButtonPosition : undefined; } set dropDownButtonPosition(value: DropDownButtonPosition | string) { this.nativeElement ? this.nativeElement.dropDownButtonPosition = value : undefined; } /** @description Sets the height of the drop down. By default it's set to an empty string. In this case the height of the drop down is controlled by a CSS variable. */ @Input() get dropDownHeight(): string | number { return this.nativeElement ? this.nativeElement.dropDownHeight : undefined; } set dropDownHeight(value: string | number) { this.nativeElement ? this.nativeElement.dropDownHeight = value : undefined; } /** @description Sets the width of the drop down. By default it's set to an empty string. In this case the width of the drop down is controlled by a CSS variable. */ @Input() get dropDownWidth(): string | number { return this.nativeElement ? this.nativeElement.dropDownWidth : undefined; } set dropDownWidth(value: string | number) { this.nativeElement ? this.nativeElement.dropDownWidth = value : undefined; } /** @description Sets or gets an object specifying strings used in the widget that can be localized. Used in conjunction with the property locale. */ @Input() get messages(): any { return this.nativeElement ? this.nativeElement.messages : undefined; } set messages(value: any) { this.nativeElement ? this.nativeElement.messages = value : undefined; } /** @description Sets or gets the unlockKey which unlocks the product. */ @Input() get unlockKey(): string { return this.nativeElement ? this.nativeElement.unlockKey : undefined; } set unlockKey(value: string) { this.nativeElement ? this.nativeElement.unlockKey = value : undefined; } /** @description Sets or gets the name attribute for the element. Name is used when submiting data inside an HTML form. */ @Input() get name(): string { return this.nativeElement ? this.nativeElement.name : undefined; } set name(value: string) { this.nativeElement ? this.nativeElement.name = value : undefined; } /** @description Determines whether the input will be in international or national mode i.e whether the input will start with '+'. */ @Input() get nationalMode(): boolean { return this.nativeElement ? this.nativeElement.nationalMode : undefined; } set nationalMode(value: boolean) { this.nativeElement ? this.nativeElement.nationalMode = value : undefined; } /** @description Determines whether the drop down is opened or not. */ @Input() get opened(): boolean { return this.nativeElement ? this.nativeElement.opened : undefined; } set opened(value: boolean) { this.nativeElement ? this.nativeElement.opened = value : undefined; } /** @description Sets or gets an array of country codes which will be used instead of the default one with all countries. The country code should be ISO 3166-1 alpha-2 codes(https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). */ @Input() get onlyCountries(): any { return this.nativeElement ? this.nativeElement.onlyCountries : undefined; } set onlyCountries(value: any) { this.nativeElement ? this.nativeElement.onlyCountries = value : undefined; } /** @description Determines the placeholder of the input. */ @Input() get placeholder(): string { return this.nativeElement ? this.nativeElement.placeholder : undefined; } set placeholder(value: string) { this.nativeElement ? this.nativeElement.placeholder = value : undefined; } /** @description Sets or gets the selected country of the element. The country code should be ISO 3166-1 alpha-2 codes(https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). */ @Input() get selectedCountry(): string { return this.nativeElement ? this.nativeElement.selectedCountry : undefined; } set selectedCountry(value: string) { this.nativeElement ? this.nativeElement.selectedCountry = value : undefined; } /** @description Sets or gets the value indicating whether the element is aligned to support locales using right-to-left fonts. */ @Input() get rightToLeft(): boolean { return this.nativeElement ? this.nativeElement.rightToLeft : undefined; } set rightToLeft(value: boolean) { this.nativeElement ? this.nativeElement.rightToLeft = value : undefined; } /** @description Determines the theme for the element. Themes define the look of the elements. */ @Input() get theme(): string { return this.nativeElement ? this.nativeElement.theme : undefined; } set theme(value: string) { this.nativeElement ? this.nativeElement.theme = value : undefined; } /** @description If is set to true, the element cannot be focused. */ @Input() get unfocusable(): boolean { return this.nativeElement ? this.nativeElement.unfocusable : undefined; } set unfocusable(value: boolean) { this.nativeElement ? this.nativeElement.unfocusable = value : undefined; } /** @description Sets or gets the value of the element. */ @Input() get value(): string { return this.nativeElement ? this.nativeElement.value : undefined; } set value(value: string) { this.nativeElement ? this.nativeElement.value = value : undefined; } /** @description This event is triggered when the selection is changed. * @param event. The custom event. Custom event was created with: event.detail( label, oldLabel, oldValue, value) * label - The label of the new selected item. * oldLabel - The label of the item that was previously selected before the event was triggered. * oldValue - The value of the item that was previously selected before the event was triggered. * value - The value of the new selected item. */ @Output() onChange: EventEmitter<CustomEvent> = new EventEmitter(); /** @description This event is triggered on each key up event of the Input, if the value is changed. * @param event. The custom event. Custom event was created with: event.detail( oldValue, value) * oldValue - The previous value before it was changed. * value - The new value. */ @Output() onChanging: EventEmitter<CustomEvent> = new EventEmitter(); /** @description This event is triggered when the user clicks on an item from the popup list. * @param event. The custom event. Custom event was created with: event.detail( item, label, value) * item - The item that was clicked. * label - The label of the item that was clicked. * value - The value of the item that was clicked. */ @Output() onItemClick: EventEmitter<CustomEvent> = new EventEmitter(); /** @description Closes the drop down. */ public close(): void { if (this.nativeElement.isRendered) { this.nativeElement.close(); } else { this.nativeElement.whenRendered(() => { this.nativeElement.close(); }); } } /** @description Ensures that the active ( selected ) item is always visible. */ public ensureVisible(): void { if (this.nativeElement.isRendered) { this.nativeElement.ensureVisible(); } else { this.nativeElement.whenRendered(() => { this.nativeElement.ensureVisible(); }); } } /** @description Returns the entered phone number with formatting. * @param {boolean} isInternational?. When you use 'false', the national phone number will be returned and the international phone number, when you use 'true' as parameter. * @returns {string} */ public async getNumberAsync(isInternational?): Promise<any> { const getResultOnRender = () => { return new Promise(resolve => { this.nativeElement.whenRendered(() => { const result = this.nativeElement.getNumber(isInternational); resolve(result) }); }); }; const result = await getResultOnRender(); return result; } public getNumber(isInternational?): string { if (this.nativeElement.isRendered) { return this.nativeElement.getNumber(isInternational); } return null; } /** @description Returns an item by its country dial code. The item is an object with 'label', 'value', 'iso2' and 'dialCode' properties. * @param {string} dialCode?. Returns the national or international phone number * @returns {any} */ public async getItemByDialCodeAsync(dialCode?): Promise<any> { const getResultOnRender = () => { return new Promise(resolve => { this.nativeElement.whenRendered(() => { const result = this.nativeElement.getItemByDialCode(dialCode); resolve(result) }); }); }; const result = await getResultOnRender(); return result; } public getItemByDialCode(dialCode?): any { if (this.nativeElement.isRendered) { return this.nativeElement.getItemByDialCode(dialCode); } return null; } /** @description Returns the selected item. The item is an object with 'label', 'value', 'iso2' and 'dialCode' properties. * @returns {any} */ public async getSelectedItemAsync(): Promise<any> { const getResultOnRender = () => { return new Promise(resolve => { this.nativeElement.whenRendered(() => { const result = this.nativeElement.getSelectedItem(); resolve(result) }); }); }; const result = await getResultOnRender(); return result; } public getSelectedItem(): any { if (this.nativeElement.isRendered) { return this.nativeElement.getSelectedItem(); } return null; } /** @description Returns true or false depending on whether the entered phone number is valid. * @returns {boolean} */ public async isValidNumberAsync(): Promise<any> { const getResultOnRender = () => { return new Promise(resolve => { this.nativeElement.whenRendered(() => { const result = this.nativeElement.isValidNumber(); resolve(result) }); }); }; const result = await getResultOnRender(); return result; } public isValidNumber(): boolean { if (this.nativeElement.isRendered) { return this.nativeElement.isValidNumber(); } return null; } /** @description Validates the entered phone number. */ public validate(): void { if (this.nativeElement.isRendered) { this.nativeElement.validate(); } else { this.nativeElement.whenRendered(() => { this.nativeElement.validate(); }); } } /** @description Opens the drop down. */ public open(): void { if (this.nativeElement.isRendered) { this.nativeElement.open(); } else { this.nativeElement.whenRendered(() => { this.nativeElement.open(); }); } } /** @description Selects the text inside the input or if it is readonly then the element is focused. */ public select(): void { if (this.nativeElement.isRendered) { this.nativeElement.select(); } else { this.nativeElement.whenRendered(() => { this.nativeElement.select(); }); } } get isRendered(): boolean { return this.nativeElement ? this.nativeElement.isRendered : false; } ngOnInit() { } ngAfterViewInit() { const that = this; that.onCreate.emit(that.nativeElement); if (Smart) Smart.Render(); this.nativeElement.classList.add('smart-angular'); if (this.nativeElement.whenRendered) this.nativeElement.whenRendered(() => { that.onReady.emit(that.nativeElement); }); this.listen(); } ngOnDestroy() { this.unlisten(); } _initialChange = true; get ngValue(): any { if (!this.nativeElement) { return null; } const value = this.nativeElement.value; return value; } set ngValue(value: any) { if (this.nativeElement) { this.writeValue(value); } } writeValue(value: any): void { const that = this; const normalizedValue = value == null ? '' : value; that.nativeElement.whenRendered(() => { that.value = normalizedValue; if (that._initialChange === false) { that._onChange(that.value); } }); } registerOnChange(fn: any): void { this._onChange = fn; } registerOnTouched(fn: any): void { this._onTouched = fn; } ngOnChanges(changes: SimpleChanges) { if (this.nativeElement && this.nativeElement.isRendered) { for (const propName in changes) { if (changes.hasOwnProperty(propName)) { this.nativeElement[propName] = changes[propName].currentValue; } } } } /** @description Add event listeners. */ private listen(): void { const that = this; that.eventHandlers['changeHandler'] = (event: CustomEvent) => { that.onChange.emit(event); } that.nativeElement.addEventListener('change', that.eventHandlers['changeHandler']); that.eventHandlers['changingHandler'] = (event: CustomEvent) => { that.onChanging.emit(event); } that.nativeElement.addEventListener('changing', that.eventHandlers['changingHandler']); that.eventHandlers['itemClickHandler'] = (event: CustomEvent) => { that.onItemClick.emit(event); } that.nativeElement.addEventListener('itemClick', that.eventHandlers['itemClickHandler']); that.eventHandlers['changeModelHandler'] = (event: Event) => { that._initialChange = false; that._onChange(that.nativeElement.value); }; that.eventHandlers['blurModelHandler'] = (event: Event) => { that._onTouched(); }; that.nativeElement.whenRendered(() => { if (that.nativeElement.querySelector('input')) { that.eventHandlers['keyupModelHandler'] = (event) => { setTimeout(() => { that.eventHandlers['changeModelHandler'](event); }, 50); }; that.nativeElement.querySelector('input').addEventListener('keyup', that.eventHandlers['keyupModelHandler']); } }); that.nativeElement.addEventListener('change', that.eventHandlers['changeModelHandler']); that.nativeElement.addEventListener('blur', that.eventHandlers['blurModelHandler']); } /** @description Remove event listeners. */ private unlisten(): void { const that = this; if (that.eventHandlers['changeHandler']) { that.nativeElement.removeEventListener('change', that.eventHandlers['changeHandler']); } if (that.eventHandlers['changingHandler']) { that.nativeElement.removeEventListener('changing', that.eventHandlers['changingHandler']); } if (that.eventHandlers['itemClickHandler']) { that.nativeElement.removeEventListener('itemClick', that.eventHandlers['itemClickHandler']); } if (that.eventHandlers['changeModelHandler']) { that.nativeElement.removeEventListener('change', that.eventHandlers['changeModelHandler']); if (that.nativeElement.querySelector('input')) { that.nativeElement.querySelector('input').removeEventListener('keyup', that.eventHandlers['keyupModelHandler']); } } if (that.eventHandlers['blurModelHandler']) { that.nativeElement.removeEventListener('blur', that.eventHandlers['blurModelHandler']); } } }