mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-10-08 14:51:32 +00:00
Merge pull request #686 from Alfresco/dev-denys-633
Support for Typeahead widget within Activiti form #633
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
.activiti-form-container {
|
.activiti-form-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.activiti-form-container > .mdl-card__media {
|
.activiti-form-container > .mdl-card__media {
|
||||||
|
@@ -41,11 +41,13 @@ will be removed during future revisions
|
|||||||
-->
|
-->
|
||||||
<div class="activiti-form-debug-container">
|
<div class="activiti-form-debug-container">
|
||||||
|
|
||||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="switch-1" [class.is-checked]="debugMode">
|
<div style="float: right">
|
||||||
<input type="checkbox" id="switch-1" class="mdl-switch__input" [(ngModel)]="debugMode">
|
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="switch-1" [class.is-checked]="debugMode">
|
||||||
<span class="mdl-switch__label"></span>
|
<input type="checkbox" id="switch-1" class="mdl-switch__input" [(ngModel)]="debugMode">
|
||||||
<span class="debug-toggle-text">Debug mode</span>
|
<span class="mdl-switch__label"></span>
|
||||||
</label>
|
<span class="debug-toggle-text">Debug mode</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div *ngIf="debugMode && hasForm()">
|
<div *ngIf="debugMode && hasForm()">
|
||||||
<h4>Values</h4>
|
<h4>Values</h4>
|
||||||
|
@@ -46,6 +46,9 @@
|
|||||||
<div *ngSwitchCase="'upload'">
|
<div *ngSwitchCase="'upload'">
|
||||||
<upload-widget [field]="field" (fieldChanged)="fieldChanged($event);"></upload-widget>
|
<upload-widget [field]="field" (fieldChanged)="fieldChanged($event);"></upload-widget>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngSwitchCase="'typeahead'">
|
||||||
|
<typeahead-widget [field]="field" (fieldChanged)="fieldChanged($event);"></typeahead-widget>
|
||||||
|
</div>
|
||||||
<div *ngSwitchDefault>
|
<div *ngSwitchDefault>
|
||||||
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
|
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -24,6 +24,7 @@ export class FormFieldTypes {
|
|||||||
static DISPLAY_VALUE: string = 'readonly';
|
static DISPLAY_VALUE: string = 'readonly';
|
||||||
static READONLY_TEXT: string = 'readonly-text';
|
static READONLY_TEXT: string = 'readonly-text';
|
||||||
static UPLOAD: string = 'upload';
|
static UPLOAD: string = 'upload';
|
||||||
|
static TYPEAHEAD: string = 'typeahead';
|
||||||
|
|
||||||
static READONLY_TYPES: string[] = [
|
static READONLY_TYPES: string[] = [
|
||||||
FormFieldTypes.HYPERLINK,
|
FormFieldTypes.HYPERLINK,
|
||||||
|
@@ -150,9 +150,9 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
This is needed due to Activiti issue related to reading radio button values as value string
|
This is needed due to Activiti issue related to reading radio button values as value string
|
||||||
but saving back as object: { id: <id>, name: <name> }
|
but saving back as object: { id: <id>, name: <name> }
|
||||||
*/
|
*/
|
||||||
let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
|
let rbEntry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
|
||||||
if (entry.length > 0) {
|
if (rbEntry.length > 0) {
|
||||||
this.form.values[this.id] = entry[0];
|
this.form.values[this.id] = rbEntry[0];
|
||||||
} else if (this.options.length > 0) {
|
} else if (this.options.length > 0) {
|
||||||
this.form.values[this.id] = this.options[0];
|
this.form.values[this.id] = this.options[0];
|
||||||
}
|
}
|
||||||
@@ -164,6 +164,14 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
this.form.values[this.id] = null;
|
this.form.values[this.id] = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FormFieldTypes.TYPEAHEAD:
|
||||||
|
let taEntry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
|
||||||
|
if (taEntry.length > 0) {
|
||||||
|
this.form.values[this.id] = taEntry[0];
|
||||||
|
} else if (this.options.length > 0) {
|
||||||
|
this.form.values[this.id] = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!FormFieldTypes.isReadOnlyType(this.type)) {
|
if (!FormFieldTypes.isReadOnlyType(this.type)) {
|
||||||
this.form.values[this.id] = this.value;
|
this.form.values[this.id] = this.value;
|
||||||
|
@@ -28,6 +28,7 @@ import { RadioButtonsWidget } from './radio-buttons/radio-buttons.widget';
|
|||||||
import { DisplayValueWidget } from './display-value/display-value.widget';
|
import { DisplayValueWidget } from './display-value/display-value.widget';
|
||||||
import { DisplayTextWidget } from './display-text/display-text.widget';
|
import { DisplayTextWidget } from './display-text/display-text.widget';
|
||||||
import { UploadWidget } from './upload/upload.widget';
|
import { UploadWidget } from './upload/upload.widget';
|
||||||
|
import { TypeaheadWidget } from './typeahead/typeahead.widget';
|
||||||
|
|
||||||
// core
|
// core
|
||||||
export * from './widget.component';
|
export * from './widget.component';
|
||||||
@@ -48,6 +49,7 @@ export * from './radio-buttons/radio-buttons.widget';
|
|||||||
export * from './display-value/display-value.widget';
|
export * from './display-value/display-value.widget';
|
||||||
export * from './display-text/display-text.widget';
|
export * from './display-text/display-text.widget';
|
||||||
export * from './upload/upload.widget';
|
export * from './upload/upload.widget';
|
||||||
|
export * from './typeahead/typeahead.widget';
|
||||||
|
|
||||||
export const CONTAINER_WIDGET_DIRECTIVES: [any] = [
|
export const CONTAINER_WIDGET_DIRECTIVES: [any] = [
|
||||||
TabsWidget,
|
TabsWidget,
|
||||||
@@ -64,7 +66,8 @@ export const PRIMITIVE_WIDGET_DIRECTIVES: [any] = [
|
|||||||
RadioButtonsWidget,
|
RadioButtonsWidget,
|
||||||
DisplayValueWidget,
|
DisplayValueWidget,
|
||||||
DisplayTextWidget,
|
DisplayTextWidget,
|
||||||
UploadWidget
|
UploadWidget,
|
||||||
|
TypeaheadWidget
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
.typeahead-widget {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeahead-autocomplete {
|
||||||
|
background-color: #fff;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 5;
|
||||||
|
color: #555;
|
||||||
|
margin: -15px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeahead-autocomplete > ul {
|
||||||
|
list-style-type: none;
|
||||||
|
position: static;
|
||||||
|
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
min-width: 124px;
|
||||||
|
padding: 8px 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeahead-autocomplete > ul > li {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label typeahead-widget"
|
||||||
|
[class.is-dirty]="value">
|
||||||
|
<input class="mdl-textfield__input"
|
||||||
|
type="text"
|
||||||
|
[attr.id]="field.id"
|
||||||
|
[(ngModel)]="value"
|
||||||
|
(ngModelChange)="checkVisibility(field)"
|
||||||
|
(keyup)="onKeyUp($event)"
|
||||||
|
(blur)="onBlur()"
|
||||||
|
[disabled]="field.readOnly">
|
||||||
|
<label class="mdl-textfield__label" [attr.for]="field.id">{{field.name}}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="typeahead-autocomplete mdl-shadow--2dp" *ngIf="popupVisible">
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let item of getOptions()"
|
||||||
|
class="mdl-menu__item"
|
||||||
|
(click)="onItemClick(item, $event)">
|
||||||
|
{{item.name}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
@@ -0,0 +1,298 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { it, describe, expect, beforeEach } from '@angular/core/testing';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { TypeaheadWidget } from './typeahead.widget';
|
||||||
|
import { FormService } from '../../../services/form.service';
|
||||||
|
import { FormModel } from '../core/form.model';
|
||||||
|
import { FormFieldModel } from '../core/form-field.model';
|
||||||
|
import { FormFieldOption } from '../core/form-field-option';
|
||||||
|
|
||||||
|
describe('TypeaheadWidget', () => {
|
||||||
|
|
||||||
|
let formService: FormService;
|
||||||
|
let widget: TypeaheadWidget;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
formService = new FormService(null, null);
|
||||||
|
widget = new TypeaheadWidget(formService);
|
||||||
|
widget.field = new FormFieldModel(new FormModel());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should request field values from service', () => {
|
||||||
|
const taskId = '<form-id>';
|
||||||
|
const fieldId = '<field-id>';
|
||||||
|
|
||||||
|
let form = new FormModel({
|
||||||
|
taskId: taskId
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.field = new FormFieldModel(form, {
|
||||||
|
id: fieldId
|
||||||
|
});
|
||||||
|
|
||||||
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||||
|
observer.next(null);
|
||||||
|
observer.complete();
|
||||||
|
}));
|
||||||
|
widget.ngOnInit();
|
||||||
|
expect(formService.getRestFieldValues).toHaveBeenCalledWith(taskId, fieldId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle error when requesting fields', () => {
|
||||||
|
const err = 'Error';
|
||||||
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.throw(err));
|
||||||
|
spyOn(widget, 'handleError').and.callThrough();
|
||||||
|
|
||||||
|
widget.ngOnInit();
|
||||||
|
|
||||||
|
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||||
|
expect(widget.handleError).toHaveBeenCalledWith(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log error to console by default', () => {
|
||||||
|
spyOn(console, 'error').and.stub();
|
||||||
|
widget.handleError('Err');
|
||||||
|
expect(console.error).toHaveBeenCalledWith('Err');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show popup on key up', () => {
|
||||||
|
widget.minTermLength = 1;
|
||||||
|
widget.value = 'some value';
|
||||||
|
|
||||||
|
widget.popupVisible = false;
|
||||||
|
widget.onKeyUp(null);
|
||||||
|
expect(widget.popupVisible).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should require value to show popup', () => {
|
||||||
|
widget.minTermLength = 1;
|
||||||
|
widget.value = '';
|
||||||
|
|
||||||
|
widget.popupVisible = false;
|
||||||
|
widget.onKeyUp(null);
|
||||||
|
expect(widget.popupVisible).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should require value to be of min length to show popup', () => {
|
||||||
|
widget.minTermLength = 3;
|
||||||
|
widget.value = 'v';
|
||||||
|
|
||||||
|
// value less than constraint
|
||||||
|
widget.popupVisible = false;
|
||||||
|
widget.onKeyUp(null);
|
||||||
|
expect(widget.popupVisible).toBeFalsy();
|
||||||
|
|
||||||
|
// value satisfies constraint
|
||||||
|
widget.value = 'value';
|
||||||
|
widget.onKeyUp(null);
|
||||||
|
expect(widget.popupVisible).toBeTruthy();
|
||||||
|
|
||||||
|
// value gets less than allowed again
|
||||||
|
widget.value = 'va';
|
||||||
|
widget.onKeyUp(null);
|
||||||
|
expect(widget.popupVisible).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should flush value on blur', (done) => {
|
||||||
|
spyOn(widget, 'flushValue').and.stub();
|
||||||
|
widget.onBlur();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(widget.flushValue).toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
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'
|
||||||
|
};
|
||||||
|
|
||||||
|
widget.onItemClick(option, null);
|
||||||
|
expect(widget.field.value).toBe(option.id);
|
||||||
|
expect(widget.value).toBe(option.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setup initial value', () => {
|
||||||
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||||
|
observer.next([
|
||||||
|
{ id: '1', name: 'One' },
|
||||||
|
{ id: '2', name: 'Two' }
|
||||||
|
]);
|
||||||
|
observer.complete();
|
||||||
|
}));
|
||||||
|
|
||||||
|
widget.field.value = '2';
|
||||||
|
widget.ngOnInit();
|
||||||
|
|
||||||
|
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||||
|
expect(widget.value).toBe('Two');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not setup initial value due to missing option', () => {
|
||||||
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||||
|
observer.next([
|
||||||
|
{ id: '1', name: 'One' },
|
||||||
|
{ id: '2', name: 'Two' }
|
||||||
|
]);
|
||||||
|
observer.complete();
|
||||||
|
}));
|
||||||
|
|
||||||
|
widget.field.value = '3';
|
||||||
|
widget.ngOnInit();
|
||||||
|
|
||||||
|
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||||
|
expect(widget.value).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setup field options on load', () => {
|
||||||
|
let options: FormFieldOption[] = [
|
||||||
|
{ id: '1', name: 'One' },
|
||||||
|
{ id: '2', name: 'Two' }
|
||||||
|
];
|
||||||
|
|
||||||
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||||
|
observer.next(options);
|
||||||
|
observer.complete();
|
||||||
|
}));
|
||||||
|
|
||||||
|
widget.ngOnInit();
|
||||||
|
expect(widget.field.options).toEqual(options);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update form upon options setup', () => {
|
||||||
|
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||||
|
observer.next([]);
|
||||||
|
observer.complete();
|
||||||
|
}));
|
||||||
|
|
||||||
|
spyOn(widget.field, 'updateForm').and.callThrough();
|
||||||
|
widget.ngOnInit();
|
||||||
|
expect(widget.field.updateForm).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get filtered options', () => {
|
||||||
|
let options: FormFieldOption[] = [
|
||||||
|
{ id: '1', name: 'Item one' },
|
||||||
|
{ id: '2', name: 'Item two'}
|
||||||
|
];
|
||||||
|
widget.field.options = options;
|
||||||
|
widget.value = 'tw';
|
||||||
|
|
||||||
|
let filtered = widget.getOptions();
|
||||||
|
expect(filtered.length).toBe(1);
|
||||||
|
expect(filtered[0]).toEqual(options[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be case insensitive when filtering options', () => {
|
||||||
|
let options: FormFieldOption[] = [
|
||||||
|
{ id: '1', name: 'Item one' },
|
||||||
|
{ id: '2', name: 'iTEM TWo' }
|
||||||
|
];
|
||||||
|
widget.field.options = options;
|
||||||
|
widget.value = 'tW';
|
||||||
|
|
||||||
|
let filtered = widget.getOptions();
|
||||||
|
expect(filtered.length).toBe(1);
|
||||||
|
expect(filtered[0]).toEqual(options[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide popup on flush', () => {
|
||||||
|
widget.popupVisible = true;
|
||||||
|
widget.flushValue();
|
||||||
|
expect(widget.popupVisible).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@@ -0,0 +1,114 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormService } from './../../../services/form.service';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
import { FormFieldOption } from './../core/form-field-option';
|
||||||
|
|
||||||
|
declare let __moduleName: string;
|
||||||
|
declare var componentHandler;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: __moduleName,
|
||||||
|
selector: 'typeahead-widget',
|
||||||
|
templateUrl: './typeahead.widget.html',
|
||||||
|
styleUrls: ['./typeahead.widget.css']
|
||||||
|
})
|
||||||
|
export class TypeaheadWidget extends WidgetComponent implements OnInit {
|
||||||
|
|
||||||
|
popupVisible: boolean = false;
|
||||||
|
minTermLength: number = 1;
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
constructor(private formService: FormService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.formService
|
||||||
|
.getRestFieldValues(
|
||||||
|
this.field.form.taskId,
|
||||||
|
this.field.id
|
||||||
|
)
|
||||||
|
.subscribe(
|
||||||
|
(result: FormFieldOption[]) => {
|
||||||
|
let options = result || [];
|
||||||
|
this.field.options = options;
|
||||||
|
this.field.updateForm();
|
||||||
|
|
||||||
|
let fieldValue = this.field.value;
|
||||||
|
if (fieldValue) {
|
||||||
|
let toSelect = options.find(item => item.id === fieldValue);
|
||||||
|
if (toSelect) {
|
||||||
|
this.value = toSelect.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptions(): FormFieldOption[] {
|
||||||
|
let val = this.value.toLocaleLowerCase();
|
||||||
|
return this.field.options.filter(item => {
|
||||||
|
let name = item.name.toLocaleLowerCase();
|
||||||
|
return name.indexOf(val) > -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyUp(event: KeyboardEvent) {
|
||||||
|
this.popupVisible = !!(this.value && this.value.length >= this.minTermLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBlur() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.flushValue();
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
flushValue() {
|
||||||
|
this.popupVisible = false;
|
||||||
|
|
||||||
|
let options = this.field.options || [];
|
||||||
|
let field = options.find(item => item.name.toLocaleLowerCase() === this.value.toLocaleLowerCase());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(error: any) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -212,6 +212,12 @@ export class FormService {
|
|||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRestFieldValues(taskId: string, field: string): Observable<any> {
|
||||||
|
let alfrescoApi = this.authService.getAlfrescoApi();
|
||||||
|
return Observable.fromPromise(alfrescoApi.activiti.taskFormsApi.getRestFieldValues(taskId, field));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
getFormId(res: any) {
|
getFormId(res: any) {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user