UNPKG

angular2-json-schema-form

Version:
115 lines (107 loc) 4.53 kB
import { Component, Input, OnInit } from '@angular/core'; import { AbstractControl } from '@angular/forms'; import { JsonSchemaFormService } from '../../library/json-schema-form.service'; import { getControl, inArray, isDefined } from '../../library/utilities/index'; @Component({ selector: 'material-number-widget', template: ` <section [class]="options?.htmlClass"> <md-input #inputControl [attr.aria-describedby]="'control' + layoutNode?._id + 'Status'" [attr.max]="options?.maximum" [attr.min]="options?.minimum" [attr.placeholder]="options?.placeholder" [required]="options?.required" [attr.readonly]="options?.readonly ? 'readonly' : null" [attr.step]="options?.multipleOf || options?.step || 'any'" [class]="options?.fieldHtmlClass" [disabled]="controlDisabled" [id]="'control' + layoutNode?._id" [name]="controlName" [placeholder]="options?.title" [readonly]="options?.readonly ? 'readonly' : null" [style.width]="'100%'" [title]="lastValidNumber" [type]="layoutNode?.type === 'range' ? 'range' : 'number'" [value]="controlValue" (input)="updateValue($event)" (keydown)="validateInput($event)" (keyup)="validateNumber($event)"> <span *ngIf="options?.fieldAddonLeft" md-prefix>{{options?.fieldAddonLeft}}</span> <span *ngIf="options?.fieldAddonRight" md-suffix>{{options?.fieldAddonRight}}</span> <md-hint *ngIf="options?.description && !(options?.placeholder && !formControl?.dirty)" align="end">{{options?.description}}</md-hint> <md-hint *ngIf="!options?.description && options?.placeholder && !formControl?.dirty" align="end">{{options?.placeholder}}</md-hint> </md-input> {{layoutNode?.type === 'range' ? controlValue : ''}} </section>`, styles: [`md-input { margin-top: 6px; }`], }) export class MaterialNumberComponent implements OnInit { private formControl: AbstractControl; private controlName: string; private controlValue: any; private controlDisabled: boolean = false; private boundControl: boolean = false; private options: any; private allowNegative: boolean = true; private allowDecimal: boolean = true; private allowExponents: boolean = false; private lastValidNumber: string = ''; @Input() formID: number; @Input() layoutNode: any; @Input() layoutIndex: number[]; @Input() dataIndex: number[]; constructor( private jsf: JsonSchemaFormService ) { } ngOnInit() { this.options = this.layoutNode.options; this.jsf.initializeControl(this); if (this.layoutNode.dataType === 'integer') this.allowDecimal = false; } private updateValue(event) { this.jsf.updateValue(this, event.target.value); } private validateInput(event) { const val = event.target.value; if (/^Digit\d$/.test(event.code)) return true; if (/^Numpad\d$/.test(event.code)) return true; if (/^Arrow/.test(event.code)) return true; if (inArray(event.code, ['Backspace', 'Delete', 'Enter', 'Escape', 'NumpadEnter', 'PrintScreen', 'Tab'])) return true; if (event.ctrlKey || event.altKey || event.metaKey) return true; if (this.allowDecimal && event.key === '.' && val.indexOf('.') === -1) return true; if (this.allowExponents) { const hasExponent = /e/i.test(val); if (/^e$/i.test(event.key) && !hasExponent && val) return true; if (event.key === '-') { const minusCount = (val.match(/\-/g) || []).length; if ((this.allowNegative || hasExponent) && !minusCount) return true; if (this.allowNegative && hasExponent && minusCount === 1) return true; } } else if (this.allowNegative && event.key === '-' && val.indexOf('-') === -1) { return true; } // TODO: Display feedback for rejected keystroke, // and clear feedback on next valid keystroke return false; } private validateNumber(event) { // TODO: This only works for input type=text - make it work for type=number const val = event.target.value; if (!isNaN(val) || val === '' || val === '.' || val === '-' || val === '-.' || (val.length > 1 && val.slice(-1).toLowerCase() === 'e') || (val.length > 2 && val.slice(-2).toLowerCase() === 'e-') ) { this.lastValidNumber = val; } else { // TODO: Display feedback for rejected key this.jsf.getControl(this).setValue(this.lastValidNumber); } } }