mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-19 17:14:57 +00:00
[ADF-147] Add input mask to Text Widget on Form (#1885)
* ADF-147 create directive to apply input mask * ADF-147 - created directive for calculate input mask * ADF-147 added input mask for text element
This commit is contained in:
parent
b79ee13d11
commit
e8889a5adb
@ -30,7 +30,7 @@ import { WidgetVisibilityService } from './src/services/widget-visibility.servic
|
|||||||
import { ActivitiAlfrescoContentService } from './src/services/activiti-alfresco.service';
|
import { ActivitiAlfrescoContentService } from './src/services/activiti-alfresco.service';
|
||||||
import { FormRenderingService } from './src/services/form-rendering.service';
|
import { FormRenderingService } from './src/services/form-rendering.service';
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpModule } from '@angular/http';
|
||||||
import { WIDGET_DIRECTIVES } from './src/components/widgets/index';
|
import { WIDGET_DIRECTIVES, MASK_DIRECTIVE } from './src/components/widgets/index';
|
||||||
|
|
||||||
export * from './src/components/activiti-form.component';
|
export * from './src/components/activiti-form.component';
|
||||||
export * from './src/components/activiti-content.component';
|
export * from './src/components/activiti-content.component';
|
||||||
@ -67,7 +67,8 @@ export const ACTIVITI_FORM_PROVIDERS: any[] = [
|
|||||||
HttpModule
|
HttpModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
...ACTIVITI_FORM_DIRECTIVES
|
...ACTIVITI_FORM_DIRECTIVES,
|
||||||
|
...MASK_DIRECTIVE
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
...WIDGET_DIRECTIVES
|
...WIDGET_DIRECTIVES
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
"@angular/platform-browser": "~4.0.0",
|
"@angular/platform-browser": "~4.0.0",
|
||||||
"@angular/platform-browser-dynamic": "~4.0.0",
|
"@angular/platform-browser-dynamic": "~4.0.0",
|
||||||
"@angular/router": "~4.0.0",
|
"@angular/router": "~4.0.0",
|
||||||
|
|
||||||
"@angular/material": "2.0.0-beta.1",
|
"@angular/material": "2.0.0-beta.1",
|
||||||
"alfresco-js-api": "~1.4.0",
|
"alfresco-js-api": "~1.4.0",
|
||||||
"core-js": "2.4.1",
|
"core-js": "2.4.1",
|
||||||
|
@ -23,6 +23,7 @@ import { ActivitiStartForm } from './activiti-start-form.component';
|
|||||||
import { FormFieldComponent } from './form-field/form-field.component';
|
import { FormFieldComponent } from './form-field/form-field.component';
|
||||||
import { ActivitiContent } from './activiti-content.component';
|
import { ActivitiContent } from './activiti-content.component';
|
||||||
import { WIDGET_DIRECTIVES } from './widgets/index';
|
import { WIDGET_DIRECTIVES } from './widgets/index';
|
||||||
|
import { MASK_DIRECTIVE } from './widgets/index';
|
||||||
import { FormService } from './../services/form.service';
|
import { FormService } from './../services/form.service';
|
||||||
import { EcmModelService } from './../services/ecm-model.service';
|
import { EcmModelService } from './../services/ecm-model.service';
|
||||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||||
@ -47,7 +48,8 @@ describe('ActivitiStartForm', () => {
|
|||||||
ActivitiStartForm,
|
ActivitiStartForm,
|
||||||
FormFieldComponent,
|
FormFieldComponent,
|
||||||
ActivitiContent,
|
ActivitiContent,
|
||||||
...WIDGET_DIRECTIVES
|
...WIDGET_DIRECTIVES,
|
||||||
|
...MASK_DIRECTIVE
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
|
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
|
||||||
|
@ -21,6 +21,7 @@ import { FormFieldComponent } from './form-field.component';
|
|||||||
import { FormRenderingService } from './../../services/form-rendering.service';
|
import { FormRenderingService } from './../../services/form-rendering.service';
|
||||||
import { FormModel, FormFieldModel, FormFieldTypes } from './../widgets/core/index';
|
import { FormModel, FormFieldModel, FormFieldTypes } from './../widgets/core/index';
|
||||||
import { TextWidget } from './../widgets/text/text.widget';
|
import { TextWidget } from './../widgets/text/text.widget';
|
||||||
|
import { InputMaskDirective } from './../widgets/text/text-mask.component';
|
||||||
import { CheckboxWidget } from './../widgets/checkbox/checkbox.widget';
|
import { CheckboxWidget } from './../widgets/checkbox/checkbox.widget';
|
||||||
import { WidgetVisibilityService } from './../../services/widget-visibility.service';
|
import { WidgetVisibilityService } from './../../services/widget-visibility.service';
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ describe('FormFieldComponent', () => {
|
|||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreModule],
|
imports: [CoreModule],
|
||||||
declarations: [FormFieldComponent, TextWidget, CheckboxWidget],
|
declarations: [FormFieldComponent, TextWidget, CheckboxWidget, InputMaskDirective],
|
||||||
providers: [
|
providers: [
|
||||||
FormRenderingService,
|
FormRenderingService,
|
||||||
WidgetVisibilityService
|
WidgetVisibilityService
|
||||||
|
@ -23,6 +23,7 @@ import { FormFieldModel } from './../core/form-field.model';
|
|||||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
import { CoreModule } from 'ng2-alfresco-core';
|
import { CoreModule } from 'ng2-alfresco-core';
|
||||||
import { WIDGET_DIRECTIVES } from '../index';
|
import { WIDGET_DIRECTIVES } from '../index';
|
||||||
|
import { MASK_DIRECTIVE } from '../index';
|
||||||
import { FormFieldComponent } from './../../form-field/form-field.component';
|
import { FormFieldComponent } from './../../form-field/form-field.component';
|
||||||
import { ActivitiContent } from './../../activiti-content.component';
|
import { ActivitiContent } from './../../activiti-content.component';
|
||||||
import { fakeFormJson } from '../../../services/assets/widget-visibility.service.mock';
|
import { fakeFormJson } from '../../../services/assets/widget-visibility.service.mock';
|
||||||
@ -133,7 +134,7 @@ describe('ContainerWidget', () => {
|
|||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreModule],
|
imports: [CoreModule],
|
||||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES]
|
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES, MASK_DIRECTIVE]
|
||||||
}).compileComponents().then(() => {
|
}).compileComponents().then(() => {
|
||||||
fixture = TestBed.createComponent(ContainerWidget);
|
fixture = TestBed.createComponent(ContainerWidget);
|
||||||
containerWidgetComponent = fixture.componentInstance;
|
containerWidgetComponent = fixture.componentInstance;
|
||||||
|
@ -41,6 +41,7 @@ import { DropdownEditorComponent } from './dynamic-table/editors/dropdown/dropdo
|
|||||||
import { BooleanEditorComponent } from './dynamic-table/editors/boolean/boolean.editor';
|
import { BooleanEditorComponent } from './dynamic-table/editors/boolean/boolean.editor';
|
||||||
import { TextEditorComponent } from './dynamic-table/editors/text/text.editor';
|
import { TextEditorComponent } from './dynamic-table/editors/text/text.editor';
|
||||||
import { RowEditorComponent } from './dynamic-table/editors/row.editor';
|
import { RowEditorComponent } from './dynamic-table/editors/row.editor';
|
||||||
|
import { InputMaskDirective } from './text/text-mask.component';
|
||||||
|
|
||||||
// core
|
// core
|
||||||
export * from './widget.component';
|
export * from './widget.component';
|
||||||
@ -76,6 +77,7 @@ export * from './dynamic-table/editors/date/date.editor';
|
|||||||
export * from './dynamic-table/editors/dropdown/dropdown.editor';
|
export * from './dynamic-table/editors/dropdown/dropdown.editor';
|
||||||
export * from './dynamic-table/editors/boolean/boolean.editor';
|
export * from './dynamic-table/editors/boolean/boolean.editor';
|
||||||
export * from './dynamic-table/editors/text/text.editor';
|
export * from './dynamic-table/editors/text/text.editor';
|
||||||
|
export * from './text/text-mask.component';
|
||||||
|
|
||||||
export const WIDGET_DIRECTIVES: any[] = [
|
export const WIDGET_DIRECTIVES: any[] = [
|
||||||
UnknownWidget,
|
UnknownWidget,
|
||||||
@ -105,3 +107,7 @@ export const WIDGET_DIRECTIVES: any[] = [
|
|||||||
TextEditorComponent,
|
TextEditorComponent,
|
||||||
RowEditorComponent
|
RowEditorComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const MASK_DIRECTIVE: any[] = [
|
||||||
|
InputMaskDirective
|
||||||
|
];
|
||||||
|
@ -22,6 +22,7 @@ import { fakeFormJson } from '../../../services/assets/widget-visibility.service
|
|||||||
import { TabsWidget } from './tabs.widget';
|
import { TabsWidget } from './tabs.widget';
|
||||||
import { TabModel } from '../core/tab.model';
|
import { TabModel } from '../core/tab.model';
|
||||||
import { WIDGET_DIRECTIVES } from '../index';
|
import { WIDGET_DIRECTIVES } from '../index';
|
||||||
|
import { MASK_DIRECTIVE } from '../index';
|
||||||
import { FormFieldComponent } from './../../form-field/form-field.component';
|
import { FormFieldComponent } from './../../form-field/form-field.component';
|
||||||
import { ActivitiContent } from './../../activiti-content.component';
|
import { ActivitiContent } from './../../activiti-content.component';
|
||||||
import { CoreModule } from 'ng2-alfresco-core';
|
import { CoreModule } from 'ng2-alfresco-core';
|
||||||
@ -104,7 +105,7 @@ describe('TabsWidget', () => {
|
|||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreModule],
|
imports: [CoreModule],
|
||||||
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES]
|
declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES, MASK_DIRECTIVE]
|
||||||
}).compileComponents().then(() => {
|
}).compileComponents().then(() => {
|
||||||
fixture = TestBed.createComponent(TabsWidget);
|
fixture = TestBed.createComponent(TabsWidget);
|
||||||
tabWidgetComponent = fixture.componentInstance;
|
tabWidgetComponent = fixture.componentInstance;
|
||||||
|
@ -0,0 +1,223 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Directive,
|
||||||
|
ElementRef,
|
||||||
|
Renderer,
|
||||||
|
HostListener,
|
||||||
|
Input,
|
||||||
|
OnChanges,
|
||||||
|
SimpleChanges,
|
||||||
|
forwardRef
|
||||||
|
} from '@angular/core';
|
||||||
|
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
|
||||||
|
|
||||||
|
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
|
||||||
|
provide: NG_VALUE_ACCESSOR,
|
||||||
|
useExisting: forwardRef(() => InputMaskDirective),
|
||||||
|
multi: true
|
||||||
|
};
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[textMask]',
|
||||||
|
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
|
||||||
|
})
|
||||||
|
export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||||
|
|
||||||
|
@Input('textMask') inputMask: {
|
||||||
|
mask: '',
|
||||||
|
isReversed: false
|
||||||
|
};
|
||||||
|
|
||||||
|
private translationMask = {
|
||||||
|
'0': { pattern: /\d/ },
|
||||||
|
'9': { pattern: /\d/, optional: true },
|
||||||
|
'#': { pattern: /\d/, recursive: true },
|
||||||
|
'A': { pattern: /[a-zA-Z0-9]/ },
|
||||||
|
'S': { pattern: /[a-zA-Z]/ }
|
||||||
|
};
|
||||||
|
|
||||||
|
private byPassKeys = [9, 16, 17, 18, 36, 37, 38, 39, 40, 91];
|
||||||
|
private value;
|
||||||
|
private invalidCharacters = [];
|
||||||
|
|
||||||
|
constructor(private el: ElementRef, private render: Renderer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_onChange = (_: any) => {
|
||||||
|
}
|
||||||
|
|
||||||
|
_onTouched = () => {
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('input', ['$event'])
|
||||||
|
@HostListener('keyup', ['$event']) onTextInput(event: KeyboardEvent) {
|
||||||
|
if (this.inputMask && this.inputMask.mask) {
|
||||||
|
this.maskValue(this.el.nativeElement.value, this.el.nativeElement.selectionStart,
|
||||||
|
this.inputMask.mask, this.inputMask.isReversed, event.keyCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (changes['inputMask'] && changes['inputMask'].currentValue['mask']) {
|
||||||
|
this.inputMask = changes['inputMask'].currentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeValue(value: any) {
|
||||||
|
this.el.nativeElement.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: any) {
|
||||||
|
this._onChange = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnTouched(fn: () => any): void {
|
||||||
|
this._onTouched = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private maskValue(actualValue, startCaret, maskToApply, isMaskReversed, keyCode) {
|
||||||
|
if (this.byPassKeys.indexOf(keyCode) === -1) {
|
||||||
|
let value = this.getMasked(false, actualValue, maskToApply, isMaskReversed);
|
||||||
|
let calculatedCaret = this.calculateCaretPosition(startCaret, actualValue, keyCode);
|
||||||
|
this.render.setElementAttribute(this.el.nativeElement, 'value', value);
|
||||||
|
this.el.nativeElement.value = value;
|
||||||
|
this.setValue(value);
|
||||||
|
this._onChange(value);
|
||||||
|
this.setCaretPosition(calculatedCaret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setCaretPosition(caretPosition) {
|
||||||
|
this.el.nativeElement.moveStart = caretPosition;
|
||||||
|
this.el.nativeElement.moveEnd = caretPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateCaretPosition(caretPosition, newValue, keyCode) {
|
||||||
|
let newValueLength = newValue.length;
|
||||||
|
let oldValue = this.getValue() || '';
|
||||||
|
let oldValueLength = oldValue.length;
|
||||||
|
|
||||||
|
if (keyCode === 8 && oldValue !== newValue) {
|
||||||
|
caretPosition = caretPosition - (newValue.slice(0, caretPosition).length - oldValue.slice(0, caretPosition).length);
|
||||||
|
} else if (oldValue !== newValue) {
|
||||||
|
if (caretPosition >= oldValueLength) {
|
||||||
|
caretPosition = newValueLength;
|
||||||
|
} else {
|
||||||
|
caretPosition = caretPosition + (newValue.slice(0, caretPosition).length - oldValue.slice(0, caretPosition).length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return caretPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMasked(skipMaskChars, val, mask, isReversed = false) {
|
||||||
|
let buf = [],
|
||||||
|
value = val,
|
||||||
|
maskIndex = 0,
|
||||||
|
maskLen = mask.length,
|
||||||
|
valueIndex = 0,
|
||||||
|
valueLength = value.length,
|
||||||
|
offset = 1,
|
||||||
|
addMethod = 'push',
|
||||||
|
resetPos = -1,
|
||||||
|
lastMaskChar,
|
||||||
|
lastUntranslatedMaskChar,
|
||||||
|
check;
|
||||||
|
|
||||||
|
if (isReversed) {
|
||||||
|
addMethod = 'unshift';
|
||||||
|
offset = -1;
|
||||||
|
lastMaskChar = 0;
|
||||||
|
maskIndex = maskLen - 1;
|
||||||
|
valueIndex = valueLength - 1;
|
||||||
|
} else {
|
||||||
|
lastMaskChar = maskLen - 1;
|
||||||
|
}
|
||||||
|
check = this.isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength);
|
||||||
|
while (check) {
|
||||||
|
let maskDigit = mask.charAt(maskIndex),
|
||||||
|
valDigit = value.charAt(valueIndex),
|
||||||
|
translation = this.translationMask[maskDigit];
|
||||||
|
|
||||||
|
if (translation) {
|
||||||
|
if (valDigit.match(translation.pattern)) {
|
||||||
|
buf[addMethod](valDigit);
|
||||||
|
if (translation.recursive) {
|
||||||
|
if (resetPos === -1) {
|
||||||
|
resetPos = maskIndex;
|
||||||
|
} else if (maskIndex === lastMaskChar) {
|
||||||
|
maskIndex = resetPos - offset;
|
||||||
|
}
|
||||||
|
if (lastMaskChar === resetPos) {
|
||||||
|
maskIndex -= offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
maskIndex += offset;
|
||||||
|
} else if (valDigit === lastUntranslatedMaskChar) {
|
||||||
|
lastUntranslatedMaskChar = undefined;
|
||||||
|
} else if (translation.optional) {
|
||||||
|
maskIndex += offset;
|
||||||
|
valueIndex -= offset;
|
||||||
|
} else {
|
||||||
|
this.invalidCharacters.push({
|
||||||
|
index: valueIndex,
|
||||||
|
digit: valDigit,
|
||||||
|
translated: translation.pattern
|
||||||
|
});
|
||||||
|
}
|
||||||
|
valueIndex += offset;
|
||||||
|
} else {
|
||||||
|
if (!skipMaskChars) {
|
||||||
|
buf[addMethod](maskDigit);
|
||||||
|
}
|
||||||
|
if (valDigit === maskDigit) {
|
||||||
|
valueIndex += offset;
|
||||||
|
} else {
|
||||||
|
lastUntranslatedMaskChar = maskDigit;
|
||||||
|
}
|
||||||
|
maskIndex += offset;
|
||||||
|
}
|
||||||
|
check = this.isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastMaskCharDigit = mask.charAt(lastMaskChar);
|
||||||
|
if (maskLen === valueLength + 1 && !this.translationMask[lastMaskCharDigit]) {
|
||||||
|
buf.push(lastMaskCharDigit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
private isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength) {
|
||||||
|
let check = false;
|
||||||
|
if (isReversed) {
|
||||||
|
check = (maskIndex > -1) && (valueIndex > -1);
|
||||||
|
} else {
|
||||||
|
check = (maskIndex < maskLen) && (valueIndex < valueLength);
|
||||||
|
}
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
|
private setValue(value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
[(ngModel)]="field.value"
|
[(ngModel)]="field.value"
|
||||||
(ngModelChange)="onFieldChanged(field)"
|
(ngModelChange)="onFieldChanged(field)"
|
||||||
[disabled]="field.readOnly"
|
[disabled]="field.readOnly"
|
||||||
|
[textMask]="{mask: mask, isReversed: isMaskReversed}"
|
||||||
placeholder="{{field.placeholder}}">
|
placeholder="{{field.placeholder}}">
|
||||||
<span *ngIf="field.validationSummary" class="mdl-textfield__error">{{field.validationSummary}}</span>
|
<span *ngIf="field.validationSummary" class="mdl-textfield__error">{{field.validationSummary}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { TextWidget } from './text.widget';
|
import { TextWidget } from './text.widget';
|
||||||
|
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||||
|
import { CoreModule } from 'ng2-alfresco-core';
|
||||||
|
import { InputMaskDirective } from './text-mask.component';
|
||||||
|
import { FormFieldModel } from '../core/form-field.model';
|
||||||
|
import { FormModel } from '../core/form.model';
|
||||||
|
import { FormFieldTypes } from '../core/form-field-types';
|
||||||
|
|
||||||
describe('TextWidget', () => {
|
describe('TextWidget', () => {
|
||||||
|
|
||||||
@ -25,11 +31,167 @@ describe('TextWidget', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
widget = new TextWidget();
|
widget = new TextWidget();
|
||||||
|
|
||||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||||
'upgradeAllRegistered'
|
'upgradeAllRegistered'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
window['componentHandler'] = componentHandler;
|
window['componentHandler'] = componentHandler;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when template is ready', () => {
|
||||||
|
let textWidget: TextWidget;
|
||||||
|
let fixture: ComponentFixture<TextWidget>;
|
||||||
|
let element: HTMLInputElement;
|
||||||
|
let componentHandler;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']);
|
||||||
|
window['componentHandler'] = componentHandler;
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [CoreModule],
|
||||||
|
declarations: [TextWidget, InputMaskDirective]
|
||||||
|
}).compileComponents().then(() => {
|
||||||
|
fixture = TestBed.createComponent(TextWidget);
|
||||||
|
textWidget = fixture.componentInstance;
|
||||||
|
element = fixture.nativeElement;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and mask is configured on text element', () => {
|
||||||
|
|
||||||
|
let inputElement: HTMLInputElement;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
textWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||||
|
id: 'text-id',
|
||||||
|
name: 'text-name',
|
||||||
|
value: '',
|
||||||
|
params: { inputMask: '##-##0,00%' },
|
||||||
|
type: FormFieldTypes.TEXT,
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
inputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show text widget', () => {
|
||||||
|
expect(element.querySelector('#text-id')).toBeDefined();
|
||||||
|
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prevent text to be written if is not allowed by the mask on keyUp event', async(() => {
|
||||||
|
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||||
|
|
||||||
|
inputElement.value = 'F';
|
||||||
|
textWidget.field.value = 'F';
|
||||||
|
let event: any = new Event('keyup');
|
||||||
|
event.keyCode = '70';
|
||||||
|
inputElement.dispatchEvent(event);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
inputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
expect(inputElement.value).toBe('');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should prevent text to be written if is not allowed by the mask on input event', async(() => {
|
||||||
|
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||||
|
|
||||||
|
inputElement.value = 'F';
|
||||||
|
textWidget.field.value = 'F';
|
||||||
|
inputElement.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
inputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
expect(inputElement.value).toBe('');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should allow masked configured value on keyUp event', async(() => {
|
||||||
|
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||||
|
|
||||||
|
inputElement.value = '1';
|
||||||
|
textWidget.field.value = '1';
|
||||||
|
let event: any = new Event('keyup');
|
||||||
|
event.keyCode = '49';
|
||||||
|
inputElement.dispatchEvent(event);
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let inputElement: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
expect(inputElement.value).toBe('1');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should autofill masked configured value on keyUp event', async(() => {
|
||||||
|
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||||
|
|
||||||
|
inputElement.value = '12345678';
|
||||||
|
textWidget.field.value = '12345678';
|
||||||
|
let event: any = new Event('keyup');
|
||||||
|
event.keyCode = '49';
|
||||||
|
inputElement.dispatchEvent(event);
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let inputElement: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
expect(inputElement.value).toBe('12-345,67%');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the mask is reversed ', () => {
|
||||||
|
|
||||||
|
let inputElement: HTMLInputElement;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
textWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
|
||||||
|
id: 'text-id',
|
||||||
|
name: 'text-name',
|
||||||
|
value: '',
|
||||||
|
params: { existingColspan: 1, maxColspan: 2, inputMask: "#.##0,00%", inputMaskReversed: true },
|
||||||
|
type: FormFieldTypes.TEXT,
|
||||||
|
readOnly: false
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
inputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to apply the mask reversed', async(() => {
|
||||||
|
expect(element.querySelector('#text-id')).not.toBeNull();
|
||||||
|
|
||||||
|
inputElement.value = '1234';
|
||||||
|
textWidget.field.value = '1234';
|
||||||
|
let event: any = new Event('keyup');
|
||||||
|
event.keyCode = '49';
|
||||||
|
inputElement.dispatchEvent(event);
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let inputElement: HTMLInputElement = <HTMLInputElement>element.querySelector('#text-id');
|
||||||
|
expect(inputElement.value).toBe('12,34%');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { WidgetComponent } from './../widget.component';
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -23,5 +23,15 @@ import { WidgetComponent } from './../widget.component';
|
|||||||
templateUrl: './text.widget.html',
|
templateUrl: './text.widget.html',
|
||||||
styleUrls: ['./text.widget.css']
|
styleUrls: ['./text.widget.css']
|
||||||
})
|
})
|
||||||
export class TextWidget extends WidgetComponent {
|
export class TextWidget extends WidgetComponent implements OnInit {
|
||||||
|
|
||||||
|
private mask;
|
||||||
|
private isMaskReversed;
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.field.params && this.field.params['inputMask']) {
|
||||||
|
this.mask = this.field.params['inputMask'];
|
||||||
|
this.isMaskReversed = this.field.params['inputMaskReversed'] ? this.field.params['inputMaskReversed'] : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user