mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[ADF-1625] removed wrong select into typeahed widget, readded validati… (#2411)
* #ADF-1625 removed wrong select into typeahed widget, readded validation on blur * #ADF-1625 added validator for typeahead fixed tests * #ADF-1625 removed wrong fdescribe * [ADF-1625] cleaned behaviour on typeahed * [ADF-1625] fixed some selection bug on typeahed and start fixing test * [ADF-1625] fixed typeahead test for autocomplete
This commit is contained in:
+54
@@ -18,6 +18,7 @@
|
|||||||
import { FormFieldOption } from './form-field-option';
|
import { FormFieldOption } from './form-field-option';
|
||||||
import { FormFieldTypes } from './form-field-types';
|
import { FormFieldTypes } from './form-field-types';
|
||||||
import {
|
import {
|
||||||
|
FixedValueFieldValidator,
|
||||||
MaxLengthFieldValidator,
|
MaxLengthFieldValidator,
|
||||||
MaxValueFieldValidator,
|
MaxValueFieldValidator,
|
||||||
MinLengthFieldValidator,
|
MinLengthFieldValidator,
|
||||||
@@ -533,4 +534,57 @@ describe('FormFieldValidator', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('FixedValueFieldValidator', () => {
|
||||||
|
|
||||||
|
let validator: FixedValueFieldValidator;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
validator = new FixedValueFieldValidator();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support only typeahead field', () => {
|
||||||
|
let field = new FormFieldModel(new FormModel(), {
|
||||||
|
type: FormFieldTypes.TEXT
|
||||||
|
});
|
||||||
|
expect(validator.isSupported(field)).toBeFalsy();
|
||||||
|
|
||||||
|
field = new FormFieldModel(new FormModel(), {
|
||||||
|
type: FormFieldTypes.TYPEAHEAD
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(validator.isSupported(field)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow empty values', () => {
|
||||||
|
let field = new FormFieldModel(new FormModel(), {
|
||||||
|
type: FormFieldTypes.TYPEAHEAD,
|
||||||
|
value: null,
|
||||||
|
regexPattern: 'pattern'
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(validator.validate(field)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should succeed for a valid input value in options', () => {
|
||||||
|
let field = new FormFieldModel(new FormModel(), {
|
||||||
|
type: FormFieldTypes.TYPEAHEAD,
|
||||||
|
value: '1',
|
||||||
|
options: [{id: '1', name: 'Leanne Graham'}, {id: '2', name: 'Ervin Howell'}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(validator.validate(field)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail for an invalid input value in options', () => {
|
||||||
|
let field = new FormFieldModel(new FormModel(), {
|
||||||
|
type: FormFieldTypes.TYPEAHEAD,
|
||||||
|
value: 'Lean',
|
||||||
|
options: [{id: '1', name: 'Leanne Graham'}, {id: '2', name: 'Ervin Howell'}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(validator.validate(field)).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+43
-1
@@ -366,6 +366,47 @@ export class RegExFieldValidator implements FormFieldValidator {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FixedValueFieldValidator implements FormFieldValidator {
|
||||||
|
|
||||||
|
private supportedTypes = [
|
||||||
|
FormFieldTypes.TYPEAHEAD
|
||||||
|
];
|
||||||
|
|
||||||
|
isSupported(field: FormFieldModel): boolean {
|
||||||
|
return field && this.supportedTypes.indexOf(field.type) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasValidNameOrValidId(field: FormFieldModel): boolean {
|
||||||
|
return this.hasValidName(field) || this.hasValidId(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasValidName(field: FormFieldModel) {
|
||||||
|
return field.options.find(item => item.name && item.name.toLocaleLowerCase() === field.value.toLocaleLowerCase()) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasValidId(field: FormFieldModel) {
|
||||||
|
return field.options[field.value - 1] ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasStringValue(field: FormFieldModel) {
|
||||||
|
return field.value && typeof field.value === 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
hasOptions(field: FormFieldModel) {
|
||||||
|
return field.options && field.options.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
validate(field: FormFieldModel): boolean {
|
||||||
|
if (this.isSupported(field)) {
|
||||||
|
if (this.hasStringValue(field) && this.hasOptions(field) && !this.hasValidNameOrValidId(field)) {
|
||||||
|
field.validationSummary = 'Invalid data inserted';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const FORM_FIELD_VALIDATORS = [
|
export const FORM_FIELD_VALIDATORS = [
|
||||||
new RequiredFieldValidator(),
|
new RequiredFieldValidator(),
|
||||||
new NumberFieldValidator(),
|
new NumberFieldValidator(),
|
||||||
@@ -376,5 +417,6 @@ export const FORM_FIELD_VALIDATORS = [
|
|||||||
new RegExFieldValidator(),
|
new RegExFieldValidator(),
|
||||||
new DateFieldValidator(),
|
new DateFieldValidator(),
|
||||||
new MinDateFieldValidator(),
|
new MinDateFieldValidator(),
|
||||||
new MaxDateFieldValidator()
|
new MaxDateFieldValidator(),
|
||||||
|
new FixedValueFieldValidator()
|
||||||
];
|
];
|
||||||
|
|||||||
+3
-5
@@ -10,18 +10,16 @@
|
|||||||
type="text"
|
type="text"
|
||||||
[id]="field.id"
|
[id]="field.id"
|
||||||
[(ngModel)]="value"
|
[(ngModel)]="value"
|
||||||
|
(ngModelChange)="validate()"
|
||||||
(keyup)="onKeyUp($event)"
|
(keyup)="onKeyUp($event)"
|
||||||
[disabled]="field.readOnly"
|
[disabled]="field.readOnly"
|
||||||
placeholder="{{field.placeholder}}"
|
placeholder="{{field.placeholder}}"
|
||||||
[mdAutocomplete]="auto">
|
[mdAutocomplete]="auto">
|
||||||
<md-autocomplete #auto="mdAutocomplete" (optionSelected)="onItemSelect($event.option.value)">
|
<md-autocomplete #auto="mdAutocomplete" (optionSelected)="onItemSelect($event.option.value)">
|
||||||
<md-option *ngFor="let item of options" (click)="onItemClick(item, $event)" [value]="item">
|
<md-option *ngFor="let item of options" [value]="item">
|
||||||
<span>{{item.name}}</span>
|
<span [id]="field.name+'_option_'+item.id">{{item.name}}</span>
|
||||||
</md-option>
|
</md-option>
|
||||||
</md-autocomplete>
|
</md-autocomplete>
|
||||||
<md-select class="adf-select" [id]="field.id" [(ngModel)]="field.value">
|
|
||||||
<md-option id="readonlyOption" *ngIf="isReadOnlyType()" [value]="field.value">{{field.value}}</md-option>
|
|
||||||
</md-select>
|
|
||||||
</md-input-container>
|
</md-input-container>
|
||||||
|
|
||||||
<error-widget [error]="field.validationSummary"></error-widget>
|
<error-widget [error]="field.validationSummary"></error-widget>
|
||||||
|
|||||||
+90
-126
@@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { OverlayContainer } from '@angular/cdk/overlay';
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
|
import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
|
||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
@@ -37,6 +38,7 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
let widget: TypeaheadWidgetComponent;
|
let widget: TypeaheadWidgetComponent;
|
||||||
let visibilityService: WidgetVisibilityService;
|
let visibilityService: WidgetVisibilityService;
|
||||||
let logService: LogServiceMock;
|
let logService: LogServiceMock;
|
||||||
|
let overlayContainerElement: HTMLElement;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
logService = new LogServiceMock();
|
logService = new LogServiceMock();
|
||||||
@@ -108,23 +110,6 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
expect(widget.handleError).toHaveBeenCalledWith(err);
|
expect(widget.handleError).toHaveBeenCalledWith(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prevent default behaviour on option item click', () => {
|
|
||||||
let event = jasmine.createSpyObj('event', ['preventDefault']);
|
|
||||||
widget.onItemClick(null, event);
|
|
||||||
expect(event.preventDefault).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update values on option item click', () => {
|
|
||||||
let option: FormFieldOption = <FormFieldOption> {
|
|
||||||
id: '1',
|
|
||||||
name: 'name'
|
|
||||||
};
|
|
||||||
spyOn(visibilityService, 'refreshVisibility').and.stub();
|
|
||||||
widget.onItemClick(option, null);
|
|
||||||
expect(widget.field.value).toBe(option.id);
|
|
||||||
expect(widget.value).toBe(option.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should setup initial value', () => {
|
it('should setup initial value', () => {
|
||||||
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||||
observer.next([
|
observer.next([
|
||||||
@@ -208,89 +193,6 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
expect(filtered[0]).toEqual(options[1]);
|
expect(filtered[0]).toEqual(options[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update form on value flush', () => {
|
|
||||||
spyOn(widget.field, 'updateForm').and.callThrough();
|
|
||||||
widget.flushValue();
|
|
||||||
expect(widget.field.updateForm).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should flush selected value', () => {
|
|
||||||
let options: FormFieldOption[] = [
|
|
||||||
{ id: '1', name: 'Item one' },
|
|
||||||
{ id: '2', name: 'Item Two' }
|
|
||||||
];
|
|
||||||
|
|
||||||
widget.field.options = options;
|
|
||||||
widget.value = 'Item Two';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBe(options[1].name);
|
|
||||||
expect(widget.field.value).toBe(options[1].id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be case insensitive when flushing value', () => {
|
|
||||||
let options: FormFieldOption[] = [
|
|
||||||
{ id: '1', name: 'Item one' },
|
|
||||||
{ id: '2', name: 'iTEM TWo' }
|
|
||||||
];
|
|
||||||
|
|
||||||
widget.field.options = options;
|
|
||||||
widget.value = 'ITEM TWO';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBe(options[1].name);
|
|
||||||
expect(widget.field.value).toBe(options[1].id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset fields when flushing missing option value', () => {
|
|
||||||
widget.field.options = [
|
|
||||||
{ id: '1', name: 'Item one' },
|
|
||||||
{ id: '2', name: 'Item two' }
|
|
||||||
];
|
|
||||||
widget.value = 'Missing item';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBeNull();
|
|
||||||
expect(widget.field.value).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset fields when flushing incorrect value', () => {
|
|
||||||
widget.field.options = [
|
|
||||||
{ id: '1', name: 'Item one' },
|
|
||||||
{ id: '2', name: 'Item two' }
|
|
||||||
];
|
|
||||||
widget.field.value = 'Item two';
|
|
||||||
widget.value = 'Item two!';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBeNull();
|
|
||||||
expect(widget.field.value).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset fields when flushing value having no options', () => {
|
|
||||||
widget.field.options = null;
|
|
||||||
widget.field.value = 'item 1';
|
|
||||||
widget.value = 'new item';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBeNull();
|
|
||||||
expect(widget.field.value).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit field change event on item click', () => {
|
|
||||||
let event = jasmine.createSpyObj('event', ['preventDefault']);
|
|
||||||
let fakeField = new FormFieldModel(new FormModel(), { id: 'fakeField', value: 'fakeValue' });
|
|
||||||
widget.field = fakeField;
|
|
||||||
let item = { id: 'fake-id-opt', name: 'fake-name-opt' };
|
|
||||||
widget.onItemClick(item, event);
|
|
||||||
|
|
||||||
widget.fieldChanged.subscribe((field) => {
|
|
||||||
expect(field).toBeDefined();
|
|
||||||
expect(field.id).toEqual('fakeField');
|
|
||||||
expect(field.value).toEqual('fake-id-opt');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when template is ready', () => {
|
describe('when template is ready', () => {
|
||||||
let typeaheadWidgetComponent: TypeaheadWidgetComponent;
|
let typeaheadWidgetComponent: TypeaheadWidgetComponent;
|
||||||
let fixture: ComponentFixture<TypeaheadWidgetComponent>;
|
let fixture: ComponentFixture<TypeaheadWidgetComponent>;
|
||||||
@@ -308,7 +210,19 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreModule, MaterialModule],
|
imports: [CoreModule, MaterialModule],
|
||||||
declarations: [TypeaheadWidgetComponent, ErrorWidgetComponent],
|
declarations: [TypeaheadWidgetComponent, ErrorWidgetComponent],
|
||||||
providers: [FormService, EcmModelService, WidgetVisibilityService]
|
providers: [
|
||||||
|
{provide: OverlayContainer, useFactory: () => {
|
||||||
|
overlayContainerElement = document.createElement('div');
|
||||||
|
overlayContainerElement.classList.add('cdk-overlay-container');
|
||||||
|
|
||||||
|
document.body.appendChild(overlayContainerElement);
|
||||||
|
|
||||||
|
// remove body padding to keep consistent cross-browser
|
||||||
|
document.body.style.padding = '0';
|
||||||
|
document.body.style.margin = '0';
|
||||||
|
|
||||||
|
return {getContainerElement: () => overlayContainerElement};
|
||||||
|
}}, FormService, EcmModelService, WidgetVisibilityService]
|
||||||
}).compileComponents().then(() => {
|
}).compileComponents().then(() => {
|
||||||
fixture = TestBed.createComponent(TypeaheadWidgetComponent);
|
fixture = TestBed.createComponent(TypeaheadWidgetComponent);
|
||||||
typeaheadWidgetComponent = fixture.componentInstance;
|
typeaheadWidgetComponent = fixture.componentInstance;
|
||||||
@@ -321,6 +235,33 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
TestBed.resetTestingModule();
|
TestBed.resetTestingModule();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe ('and typeahead is in readonly mode', () => {
|
||||||
|
|
||||||
|
it('should show typeahead value with input disabled', async(() => {
|
||||||
|
typeaheadWidgetComponent.field = new FormFieldModel(
|
||||||
|
new FormModel({ processVariables: [{ name: 'typeahead-id_LABEL', value: 'FakeProcessValue' }] }), {
|
||||||
|
id: 'typeahead-id',
|
||||||
|
name: 'typeahead-name',
|
||||||
|
type: 'readonly',
|
||||||
|
params: { field: { id: 'typeahead-id', name: 'typeahead-name', type: 'typeahead' } }
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let readonlyInput: HTMLInputElement = <HTMLInputElement> element.querySelector('#typeahead-id');
|
||||||
|
expect(readonlyInput.disabled).toBeTruthy();
|
||||||
|
expect(readonlyInput).not.toBeNull();
|
||||||
|
expect(readonlyInput.value).toBe('FakeProcessValue');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('and typeahead is populated via taskId', () => {
|
describe('and typeahead is populated via taskId', () => {
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
@@ -344,14 +285,58 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should show typeahead options', async(() => {
|
it('should show typeahead options', async(() => {
|
||||||
let keyboardEvent = new KeyboardEvent('keypress');
|
let typeahedElement = fixture.debugElement.query(By.css('#typeahead-id'));
|
||||||
|
let typeahedHTMLElement: HTMLInputElement = <HTMLInputElement> typeahedElement.nativeElement;
|
||||||
|
typeahedHTMLElement.focus();
|
||||||
typeaheadWidgetComponent.value = 'F';
|
typeaheadWidgetComponent.value = 'F';
|
||||||
|
typeahedHTMLElement.value = 'F';
|
||||||
|
typeahedHTMLElement.dispatchEvent(new Event('keyup'));
|
||||||
|
typeahedHTMLElement.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_1"]'))).not.toBeNull();
|
||||||
|
expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_2"]'))).not.toBeNull();
|
||||||
|
expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_3"]'))).not.toBeNull();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should hide the option when the value is empty', async(() => {
|
||||||
|
let typeahedElement = fixture.debugElement.query(By.css('#typeahead-id'));
|
||||||
|
let typeahedHTMLElement: HTMLInputElement = <HTMLInputElement> typeahedElement.nativeElement;
|
||||||
|
typeahedHTMLElement.focus();
|
||||||
|
typeaheadWidgetComponent.value = 'F';
|
||||||
|
typeahedHTMLElement.value = 'F';
|
||||||
|
typeahedHTMLElement.dispatchEvent(new Event('keyup'));
|
||||||
|
typeahedHTMLElement.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_1"]'))).not.toBeNull();
|
||||||
|
typeahedHTMLElement.focus();
|
||||||
|
typeaheadWidgetComponent.value = '';
|
||||||
|
typeahedHTMLElement.dispatchEvent(new Event('keyup'));
|
||||||
|
typeahedHTMLElement.dispatchEvent(new Event('input'));
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_1"]'))).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should show error message when the value is not valid', async(() => {
|
||||||
|
typeaheadWidgetComponent.value = 'Fake Name';
|
||||||
|
typeaheadWidgetComponent.field.value = 'Fake Name';
|
||||||
|
typeaheadWidgetComponent.field.options = fakeOptionList;
|
||||||
|
expect(element.querySelector('.adf-error-text')).toBeNull();
|
||||||
|
let keyboardEvent = new KeyboardEvent('keypress');
|
||||||
typeaheadWidgetComponent.onKeyUp(keyboardEvent);
|
typeaheadWidgetComponent.onKeyUp(keyboardEvent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
expect(fixture.debugElement.queryAll(By.css('[id="md-option-1"]'))).toBeDefined();
|
fixture.detectChanges();
|
||||||
expect(fixture.debugElement.queryAll(By.css('[id="md-option-2"]'))).toBeDefined();
|
expect(element.querySelector('.adf-error-text')).not.toBeNull();
|
||||||
expect(fixture.debugElement.queryAll(By.css('[id="md-option-3"]'))).toBeDefined();
|
expect(element.querySelector('.adf-error-text').textContent).toContain('Invalid data inserted');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -362,27 +347,6 @@ describe('TypeaheadWidgetComponent', () => {
|
|||||||
expect(element.querySelector('#typeahead-id')).toBeNull();
|
expect(element.querySelector('#typeahead-id')).toBeNull();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should show typeahead value when the type is readonly', async(() => {
|
|
||||||
typeaheadWidgetComponent.field = new FormFieldModel(
|
|
||||||
new FormModel({ taskId: 'fake-task-id', processVariables: [{ name: 'typeahead-id_LABEL', value: 'FakeProcessValue' }] }), {
|
|
||||||
id: 'typeahead-id',
|
|
||||||
name: 'typeahead-name',
|
|
||||||
type: 'readonly',
|
|
||||||
value: '9',
|
|
||||||
params: { field: { id: 'typeahead-id', name: 'typeahead-name', type: 'typeahead' } }
|
|
||||||
});
|
|
||||||
fixture.detectChanges();
|
|
||||||
const trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
|
|
||||||
trigger.click();
|
|
||||||
fixture.detectChanges();
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
expect(element.querySelector('#typeahead-id')).not.toBeNull();
|
|
||||||
let optionElement: HTMLElement = <HTMLElement> document.body.querySelector('.mat-option');
|
|
||||||
expect(optionElement.innerText).toEqual('FakeProcessValue');
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('and typeahead is populated via processDefinitionId', () => {
|
describe('and typeahead is populated via processDefinitionId', () => {
|
||||||
|
|||||||
+25
-29
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* tslint:disable:component-selector */
|
/* tslint:disable:component-selector */
|
||||||
|
|
||||||
import { ENTER, ESCAPE } from '@angular/cdk/keycodes';
|
import { ENTER, ESCAPE } from '@angular/cdk/keycodes';
|
||||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
@@ -23,7 +23,7 @@ import { LogService } from 'ng2-alfresco-core';
|
|||||||
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
|
||||||
import { FormService } from './../../../services/form.service';
|
import { FormService } from './../../../services/form.service';
|
||||||
import { FormFieldOption } from './../core/form-field-option';
|
import { FormFieldOption } from './../core/form-field-option';
|
||||||
import { baseHost , WidgetComponent } from './../widget.component';
|
import { baseHost, WidgetComponent } from './../widget.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'typeahead-widget',
|
selector: 'typeahead-widget',
|
||||||
@@ -51,6 +51,9 @@ export class TypeaheadWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
} else if (this.field.form.processDefinitionId) {
|
} else if (this.field.form.processDefinitionId) {
|
||||||
this.getValuesByProcessDefinitionId();
|
this.getValuesByProcessDefinitionId();
|
||||||
}
|
}
|
||||||
|
if (this.isReadOnlyType()) {
|
||||||
|
this.value = this.field.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getValuesByTaskId() {
|
getValuesByTaskId() {
|
||||||
@@ -104,48 +107,33 @@ export class TypeaheadWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
getOptions(): FormFieldOption[] {
|
getOptions(): FormFieldOption[] {
|
||||||
let val = this.value.toLocaleLowerCase();
|
let val = this.value.trim().toLocaleLowerCase();
|
||||||
return this.field.options.filter(item => {
|
return this.field.options.filter(item => {
|
||||||
let name = item.name.toLocaleLowerCase();
|
let name = item.name.toLocaleLowerCase();
|
||||||
return name.indexOf(val) > -1;
|
return name.indexOf(val) > -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isValidOptionName(optionName: string): boolean {
|
||||||
|
let option = this.field.options.find(item => item.name && item.name.toLocaleLowerCase() === optionName.toLocaleLowerCase());
|
||||||
|
return option ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
onKeyUp(event: KeyboardEvent) {
|
onKeyUp(event: KeyboardEvent) {
|
||||||
if (this.value && this.value.length >= this.minTermLength && this.oldValue !== this.value) {
|
if (this.value && this.value.trim().length >= this.minTermLength && this.oldValue !== this.value) {
|
||||||
if (event.keyCode !== ESCAPE && event.keyCode !== ENTER) {
|
if (event.keyCode !== ESCAPE && event.keyCode !== ENTER) {
|
||||||
if (this.value.length >= this.minTermLength) {
|
if (this.value.length >= this.minTermLength) {
|
||||||
this.options = this.getOptions();
|
this.options = this.getOptions();
|
||||||
this.oldValue = this.value;
|
this.oldValue = this.value;
|
||||||
|
if (this.isValidOptionName(this.value)) {
|
||||||
|
this.field.value = this.options[0].id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.isValueDefined() && this.value.trim().length === 0) {
|
||||||
flushValue() {
|
this.oldValue = this.value;
|
||||||
let options = this.field.options || [];
|
this.options = [];
|
||||||
let lValue = this.value ? this.value.toLocaleLowerCase() : null;
|
|
||||||
|
|
||||||
let field = options.find(item => item.name && item.name.toLocaleLowerCase() === lValue);
|
|
||||||
if (field) {
|
|
||||||
this.field.value = field.id;
|
|
||||||
this.value = field.name;
|
|
||||||
} else {
|
|
||||||
this.field.value = null;
|
|
||||||
this.value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.field.updateForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
onItemClick(item: FormFieldOption, event: Event) {
|
|
||||||
if (item) {
|
|
||||||
this.field.value = item.id;
|
|
||||||
this.value = item.name;
|
|
||||||
this.checkVisibility();
|
|
||||||
}
|
|
||||||
if (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +145,14 @@ export class TypeaheadWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
this.field.value = this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValueDefined() {
|
||||||
|
return this.value !== null && this.value !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
handleError(error: any) {
|
handleError(error: any) {
|
||||||
this.logService.error(error);
|
this.logService.error(error);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user