mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[MNT-24456] aps with adw multi user and group fields do not accept multiple values (#10636)
* [MNT-24456] Allow to select multiple users and groups for task form * [MNT-24456] Inputs styling * [MNT-24456] Unit tests, fixed issue for selecting single group * [MNT-24456] Fixed issue when completing forms with null instead of empty array * [MNT-24456] Used UnitTestingUtils where possible
This commit is contained in:
parent
430ca84c77
commit
808f836259
@ -221,6 +221,40 @@ describe('FormFieldModel', () => {
|
||||
expect(field.hasEmptyValue).toBe(false);
|
||||
});
|
||||
|
||||
it('should detect multiple values when multiple property of params is true', () => {
|
||||
const field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
options: [
|
||||
{ id: 'fake-option-1', name: 'fake label 1' },
|
||||
{ id: 'fake-option-2', name: 'fake label 2' },
|
||||
{ id: 'fake-option-3', name: 'fake label 3' }
|
||||
],
|
||||
value: [],
|
||||
params: {
|
||||
multiple: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(field.hasMultipleValues).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not detect multiple values when multiple property of params is false', () => {
|
||||
const field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DROPDOWN,
|
||||
options: [
|
||||
{ id: 'fake-option-1', name: 'fake label 1' },
|
||||
{ id: 'fake-option-2', name: 'fake label 2' },
|
||||
{ id: 'fake-option-3', name: 'fake label 3' }
|
||||
],
|
||||
value: [],
|
||||
params: {
|
||||
multiple: false
|
||||
}
|
||||
});
|
||||
|
||||
expect(field.hasMultipleValues).toBeFalse();
|
||||
});
|
||||
|
||||
describe('should leave not resolved value (in case of delayed options)', () => {
|
||||
it('when string', () => {
|
||||
const field = new FormFieldModel(new FormModel(), {
|
||||
|
@ -141,7 +141,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
}
|
||||
|
||||
get hasMultipleValues() {
|
||||
return this.selectionType === 'multiple';
|
||||
return this.selectionType === 'multiple' || this.params.multiple;
|
||||
}
|
||||
|
||||
markAsInvalid() {
|
||||
|
@ -90,6 +90,7 @@
|
||||
--adf-secondary-button-background: $adf-secondary-button-background,
|
||||
--adf-secondary-modal-text-color: $adf-secondary-modal-text-color,
|
||||
--adf-disabled-button-background: $adf-disabled-button-background,
|
||||
--adf-chip-border-color: $adf-chip-border-color,
|
||||
|
||||
--adf-display-external-property-widget-preview-selection-color: mat.get-color-from-palette($foreground, secondary-text)
|
||||
);
|
||||
|
@ -29,3 +29,4 @@ $adf-error-color: #ba1b1b;
|
||||
$adf-secondary-button-background: #2121210d;
|
||||
$adf-secondary-modal-text-color: #212121;
|
||||
$adf-disabled-button-background: rgba(0, 0, 0, 0.12);
|
||||
$adf-chip-border-color: #757575;
|
||||
|
@ -3,23 +3,41 @@
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
id="functional-group-div">
|
||||
|
||||
<mat-form-field>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
|
||||
<mat-form-field
|
||||
appearance="outline"
|
||||
class="adf-group-widget-field">
|
||||
<mat-chip-grid #chipGrid>
|
||||
<mat-chip-row
|
||||
*ngFor="let group of selectedGroups"
|
||||
(removed)="onRemove(group)"
|
||||
[disabled]="field.readOnly"
|
||||
[attr.data-automation-id]="'adf-group-widget-chip-' + group.id"
|
||||
class="adf-group-widget-field-chip">
|
||||
{{ getDisplayName(group) }}
|
||||
<button matChipRemove [attr.aria-label]="'remove ' + group.name">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-chip-row>
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
data-automation-id="adf-group-search-input"
|
||||
[matChipInputFor]="chipGrid"
|
||||
[id]="field.id"
|
||||
[formControl]="searchTerm"
|
||||
[disabled]="!multiSelect && selectedGroups.length > 0 || field.readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
(blur)="markAsTouched()"
|
||||
[matAutocomplete]="auto">
|
||||
[matAutocomplete]="auto"
|
||||
#inputValue>
|
||||
</mat-chip-grid>
|
||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="updateOption($event.option.value)" [displayWith]="getDisplayName">
|
||||
<mat-option *ngFor="let item of groups$ | async; let i = index"
|
||||
id="adf-group-widget-user-{{i}}"
|
||||
[id]="field.id +'-'+item.id"
|
||||
[value]="item">
|
||||
[id]="field.id +'-'+item.id"
|
||||
[value]="item"
|
||||
[disabled]="isGroupAlreadySelected(item)">
|
||||
<span id="adf-group-label-name">{{item.name}}</span>
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
|
@ -1,5 +1,16 @@
|
||||
.adf {
|
||||
&-group-widget {
|
||||
width: 100%;
|
||||
|
||||
.adf-group-widget-field {
|
||||
.adf-group-widget-field-chip {
|
||||
border: 1px solid var(--adf-chip-border-color);
|
||||
border-radius: 10px;
|
||||
background-color: var(--theme-primary-color-default-contrast);
|
||||
height: auto;
|
||||
word-break: break-word;
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,14 @@
|
||||
*/
|
||||
|
||||
import { of, timer } from 'rxjs';
|
||||
import { FormFieldModel, FormModel, GroupModel, CoreTestingModule, FormFieldTypes } from '@alfresco/adf-core';
|
||||
import { FormFieldModel, FormModel, GroupModel, CoreTestingModule, FormFieldTypes, UnitTestingUtils } from '@alfresco/adf-core';
|
||||
import { FunctionalGroupWidgetComponent } from './functional-group.widget';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { PeopleProcessService } from '../../../services/people-process.service';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { MatChipRowHarness } from '@angular/material/chips/testing';
|
||||
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
|
||||
|
||||
describe('FunctionalGroupWidgetComponent', () => {
|
||||
let fixture: ComponentFixture<FunctionalGroupWidgetComponent>;
|
||||
@ -27,6 +31,9 @@ describe('FunctionalGroupWidgetComponent', () => {
|
||||
let peopleProcessService: PeopleProcessService;
|
||||
let getWorkflowGroupsSpy: jasmine.Spy;
|
||||
let element: HTMLElement;
|
||||
let loader: HarnessLoader;
|
||||
let unitTestingUtils: UnitTestingUtils;
|
||||
|
||||
const groups: GroupModel[] = [
|
||||
{ id: '1', name: 'group 1' },
|
||||
{ id: '2', name: 'group 2' }
|
||||
@ -41,6 +48,8 @@ describe('FunctionalGroupWidgetComponent', () => {
|
||||
|
||||
fixture = TestBed.createComponent(FunctionalGroupWidgetComponent);
|
||||
component = fixture.componentInstance;
|
||||
unitTestingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
component.field = new FormFieldModel(new FormModel());
|
||||
element = fixture.nativeElement;
|
||||
fixture.detectChanges();
|
||||
@ -102,7 +111,7 @@ describe('FunctionalGroupWidgetComponent', () => {
|
||||
|
||||
component.updateOption(groups[1]);
|
||||
|
||||
expect(component.field.value).toBe(groups[1]);
|
||||
expect(component.field.value).toEqual(groups[1]);
|
||||
});
|
||||
|
||||
it('should fetch groups and show popup on key up', async () => {
|
||||
@ -173,4 +182,143 @@ describe('FunctionalGroupWidgetComponent', () => {
|
||||
expect(asterisk.textContent).toEqual('*');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Groups chips', () => {
|
||||
beforeEach(() => {
|
||||
component.field.value = groups;
|
||||
component.ngOnInit();
|
||||
});
|
||||
|
||||
it('should display chip for each selected group', async () => {
|
||||
fixture.detectChanges();
|
||||
expect(await loader.getAllHarnesses(MatChipRowHarness)).toHaveSize(2);
|
||||
});
|
||||
|
||||
it('should disable chips based on field readOnly property', async () => {
|
||||
component.field.readOnly = true;
|
||||
|
||||
fixture.detectChanges();
|
||||
expect((await loader.getAllHarnesses(MatChipRowHarness)).every((chip) => chip.isDisabled())).toBeTrue();
|
||||
});
|
||||
|
||||
it('should display correct group name for each chip', async () => {
|
||||
fixture.detectChanges();
|
||||
const chips = await loader.getAllHarnesses(MatChipRowHarness);
|
||||
expect(await chips[0].getText()).toBe('group 1');
|
||||
expect(await chips[1].getText()).toBe('group 2');
|
||||
});
|
||||
|
||||
it('should allow to remove chips', async () => {
|
||||
fixture.detectChanges();
|
||||
const chips = await loader.getAllHarnesses(MatChipRowHarness);
|
||||
|
||||
await chips[0].remove();
|
||||
const chipsAfterRemoving = await loader.getAllHarnesses(MatChipRowHarness);
|
||||
expect(component.field.value).toEqual([groups[1]]);
|
||||
expect(chipsAfterRemoving).toHaveSize(1);
|
||||
expect(await chipsAfterRemoving[0].getText()).toBe('group 2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Groups input', () => {
|
||||
const getInputElement = (): HTMLInputElement => unitTestingUtils.getByDataAutomationId('adf-group-search-input').nativeElement;
|
||||
|
||||
it('should disable input if multiple property of params is false, some group is selected and field is not readOnly', () => {
|
||||
component.field.params.multiple = false;
|
||||
component.field.value = [groups[0]];
|
||||
component.field.readOnly = false;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeTrue();
|
||||
});
|
||||
|
||||
it('should enable input if multiple property of params is false, none group is selected and field is not readOnly', () => {
|
||||
component.field.params.multiple = false;
|
||||
component.field.value = [];
|
||||
component.field.readOnly = false;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeFalse();
|
||||
});
|
||||
|
||||
it('should enable input if multiple property of params is true, none group is selected and field is not readOnly', () => {
|
||||
component.field.params.multiple = true;
|
||||
component.field.value = [];
|
||||
component.field.readOnly = false;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeFalse();
|
||||
});
|
||||
|
||||
it('should enable input if multiple property of params is true, some group is selected and field is not readOnly', () => {
|
||||
component.field.params.multiple = true;
|
||||
component.field.value = [groups[0]];
|
||||
component.field.readOnly = false;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeFalse();
|
||||
});
|
||||
|
||||
it('should disable input if multiple property of params is false, some group is selected and field is readOnly', () => {
|
||||
component.field.params.multiple = false;
|
||||
component.field.value = [groups[0]];
|
||||
component.field.readOnly = true;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeTrue();
|
||||
});
|
||||
|
||||
it('should disable input if multiple property of params is false, none group is selected and field is readOnly', () => {
|
||||
component.field.params.multiple = false;
|
||||
component.field.value = [];
|
||||
component.field.readOnly = true;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeTrue();
|
||||
});
|
||||
|
||||
it('should disable input if multiple property of params is true, none group is selected and field is readOnly', () => {
|
||||
component.field.params.multiple = true;
|
||||
component.field.value = [];
|
||||
component.field.readOnly = true;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeTrue();
|
||||
});
|
||||
|
||||
it('should disable input if multiple property of params is true, some group is selected and field is readOnly', () => {
|
||||
component.field.params.multiple = true;
|
||||
component.field.value = [groups[0]];
|
||||
component.field.readOnly = true;
|
||||
component.ngOnInit();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getInputElement().disabled).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Autocomplete options', () => {
|
||||
it('should have disabled already selected groups', async () => {
|
||||
component.field.params.multiple = true;
|
||||
component.ngOnInit();
|
||||
getWorkflowGroupsSpy.and.returnValue(of(groups));
|
||||
await typeIntoInput('group');
|
||||
const autocompleteHarness = await loader.getHarness(MatAutocompleteHarness);
|
||||
await autocompleteHarness.selectOption({
|
||||
text: groups[0].name
|
||||
});
|
||||
|
||||
await typeIntoInput('group');
|
||||
const options = await autocompleteHarness.getOptions();
|
||||
expect(await options[0].isDisabled()).toBeTrue();
|
||||
expect(await options[1].isDisabled()).toBeFalse();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -17,9 +17,9 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { Component, ElementRef, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { ErrorWidgetComponent, FormService, GroupModel, WidgetComponent } from '@alfresco/adf-core';
|
||||
import { catchError, debounceTime, filter, switchMap, tap } from 'rxjs/operators';
|
||||
import { catchError, debounceTime, distinctUntilChanged, switchMap, tap } from 'rxjs/operators';
|
||||
import { merge, of } from 'rxjs';
|
||||
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
|
||||
import { PeopleProcessService } from '../../../services/people-process.service';
|
||||
@ -28,11 +28,23 @@ import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
|
||||
@Component({
|
||||
selector: 'functional-group-widget',
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatFormFieldModule, TranslateModule, MatInputModule, ReactiveFormsModule, MatAutocompleteModule, ErrorWidgetComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatFormFieldModule,
|
||||
TranslateModule,
|
||||
MatInputModule,
|
||||
ReactiveFormsModule,
|
||||
MatAutocompleteModule,
|
||||
ErrorWidgetComponent,
|
||||
MatChipsModule,
|
||||
MatIconModule
|
||||
],
|
||||
templateUrl: './functional-group.widget.html',
|
||||
styleUrls: ['./functional-group.widget.scss'],
|
||||
host: {
|
||||
@ -53,16 +65,25 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O
|
||||
groupId: string;
|
||||
searchTerm = new UntypedFormControl();
|
||||
groups$ = merge(this.searchTerm.valueChanges).pipe(
|
||||
distinctUntilChanged(),
|
||||
tap((search: GroupModel | string) => {
|
||||
const isValid = typeof search !== 'string';
|
||||
const empty = search === '';
|
||||
this.updateOption(isValid ? (search as GroupModel) : null);
|
||||
this.validateGroup(isValid, empty);
|
||||
}),
|
||||
filter((group: string | GroupModel) => typeof group === 'string' && group.length >= this.minTermLength),
|
||||
debounceTime(300),
|
||||
switchMap((searchTerm: string) => this.peopleProcessService.getWorkflowGroups(searchTerm, this.groupId).pipe(catchError(() => of([]))))
|
||||
switchMap((searchTerm) => {
|
||||
if (typeof searchTerm !== 'string' || searchTerm.length < this.minTermLength) {
|
||||
return of([]);
|
||||
}
|
||||
return this.peopleProcessService.getWorkflowGroups(searchTerm, this.groupId).pipe(catchError(() => of([])));
|
||||
})
|
||||
);
|
||||
selectedGroups: GroupModel[] = [];
|
||||
multiSelect = false;
|
||||
|
||||
@ViewChild('inputValue', { static: true })
|
||||
input: ElementRef;
|
||||
|
||||
constructor(public peopleProcessService: PeopleProcessService, public formService: FormService, public elementRef: ElementRef) {
|
||||
super(formService);
|
||||
@ -70,6 +91,9 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O
|
||||
|
||||
ngOnInit() {
|
||||
if (this.field) {
|
||||
if (this.field.value) {
|
||||
Array.isArray(this.field.value) ? this.selectedGroups.push(...this.field.value) : this.selectedGroups.push(this.field.value);
|
||||
}
|
||||
if (this.field.readOnly) {
|
||||
this.searchTerm.disable();
|
||||
}
|
||||
@ -79,6 +103,10 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O
|
||||
const restrictWithGroup = params.restrictWithGroup;
|
||||
this.groupId = restrictWithGroup.id;
|
||||
}
|
||||
if (params?.multiple) {
|
||||
this.multiSelect = params.multiple;
|
||||
this.field.value = this.selectedGroups;
|
||||
}
|
||||
|
||||
if (this.field.value?.name) {
|
||||
this.searchTerm.setValue(this.field.value.name);
|
||||
@ -88,11 +116,22 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O
|
||||
|
||||
updateOption(option?: GroupModel) {
|
||||
if (option) {
|
||||
this.field.value = option;
|
||||
if (this.multiSelect) {
|
||||
if (!this.isGroupAlreadySelected(option)) {
|
||||
this.field.value = this.selectedGroups;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.field.value = option;
|
||||
}
|
||||
this.selectedGroups.push(option);
|
||||
} else {
|
||||
this.field.value = null;
|
||||
}
|
||||
|
||||
this.searchTerm.setValue('');
|
||||
this.input.nativeElement.value = '';
|
||||
this.field.updateForm();
|
||||
}
|
||||
|
||||
@ -117,4 +156,16 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
onRemove(group: GroupModel): void {
|
||||
const index = this.selectedGroups.indexOf(group);
|
||||
if (index >= 0) {
|
||||
this.selectedGroups.splice(index, 1);
|
||||
this.field.value = this.selectedGroups;
|
||||
}
|
||||
}
|
||||
|
||||
isGroupAlreadySelected(group: GroupModel): boolean {
|
||||
return this.selectedGroups?.some((selectedGroup) => selectedGroup.id === group.id);
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,20 @@
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
id="people-widget-content">
|
||||
<mat-form-field>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
|
||||
<mat-form-field
|
||||
appearance="outline"
|
||||
class="adf-people-widget-field">
|
||||
<mat-chip-grid #chipGrid [attr.aria-label]="'ADF_PROCESS_LIST.START_PROCESS.FORM.LABEL.SELECTED_PEOPLE' | translate">
|
||||
<mat-chip-row
|
||||
*ngFor="let user of selectedUsers"
|
||||
(removed)="onRemove(user)"
|
||||
[disabled]="field.readOnly"
|
||||
[attr.data-automation-id]="'adf-people-widget-chip-' + user.id">
|
||||
[attr.data-automation-id]="'adf-people-widget-chip-' + user.id"
|
||||
class="adf-people-widget-field-chip">
|
||||
{{ getDisplayName(user) }}
|
||||
<button matChipRemove [attr.aria-label]="'remove ' + user.firstName">
|
||||
<mat-icon>cancel</mat-icon>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-chip-row>
|
||||
<input #inputValue
|
||||
|
@ -7,6 +7,17 @@
|
||||
#{$mat-form-field-label} {
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.adf-people-widget-field {
|
||||
.adf-people-widget-field-chip {
|
||||
border: 1px solid var(--adf-chip-border-color);
|
||||
border-radius: 10px;
|
||||
background-color: var(--theme-primary-color-default-contrast);
|
||||
height: auto;
|
||||
word-break: break-word;
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-people-widget-list {
|
||||
|
@ -253,6 +253,20 @@ describe('PeopleWidgetComponent', () => {
|
||||
expect(widget.selectedUsers).toEqual([selectedUser]);
|
||||
});
|
||||
|
||||
it('should set default value to field value if field can have multiple values', () => {
|
||||
widget.field.params.multiple = true;
|
||||
|
||||
widget.ngOnInit();
|
||||
expect(widget.field.value).toEqual([]);
|
||||
});
|
||||
|
||||
it('should not set default value to field value if field can not have multiple values', () => {
|
||||
widget.field.params.multiple = false;
|
||||
|
||||
widget.ngOnInit();
|
||||
expect(widget.field.value).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('when is required', () => {
|
||||
beforeEach(() => {
|
||||
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
|
||||
|
@ -109,6 +109,7 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
||||
}
|
||||
if (params?.multiple) {
|
||||
this.multiSelect = params.multiple;
|
||||
this.field.value = this.selectedUsers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user