selectic 1.3.9 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Store.tsx CHANGED
@@ -1,13 +1,17 @@
1
1
  /* File Purpose:
2
2
  * It keeps and computes all states at a single place.
3
- * Every inner components of Selectic should comunicate with this file to
3
+ * Every inner components of Selectic should communicate with this file to
4
4
  * change or to get states.
5
5
  */
6
6
 
7
- import {Vue, Component, Prop, Watch} from 'vtyx';
7
+ import { reactive, watch, computed, ComputedRef } from 'vue';
8
8
 
9
9
  /* {{{ Types definitions */
10
10
 
11
+ type MandateProps<T extends {}> = {
12
+ [TK in keyof T]-?: T[TK];
13
+ }
14
+
11
15
  type voidCaller = () => void;
12
16
 
13
17
  export type StrictOptionId = string | number;
@@ -65,7 +69,7 @@ export type ListPosition =
65
69
  'bottom'
66
70
  /* Display the list at bottom */
67
71
  | 'top'
68
- /* Display the list at bootom but if there is not enough space, display it at top */
72
+ /* Display the list at bottom but if there is not enough space, display it at top */
69
73
  | 'auto';
70
74
 
71
75
  export interface SelecticStoreStateParams {
@@ -124,31 +128,34 @@ export interface SelecticStoreStateParams {
124
128
  */
125
129
  optionBehavior?: string;
126
130
 
131
+ /* Indicate where the list should be deployed */
132
+ listPosition?: ListPosition;
133
+
127
134
  /* If true, the component is open at start */
128
135
  isOpen?: boolean;
129
136
  }
130
137
 
131
138
  export interface Props {
132
139
  /* Selected value */
133
- value?: SelectedValue;
140
+ value?: SelectedValue | null;
134
141
 
135
142
  /* If true, the value represents the ones we don't want to select */
136
143
  selectionIsExcluded?: boolean;
137
144
 
138
- /* Equivalent of "disabled" select's attribute */
145
+ /* Equivalent of "disabled" Select's attribute */
139
146
  disabled?: boolean;
140
147
 
141
148
  /* List of options to display */
142
- options?: OptionProp[];
149
+ options?: OptionProp[] | null;
143
150
 
144
151
  /* List of options to display from child elements */
145
- childOptions?: OptionProp[];
152
+ childOptions?: OptionValue[];
146
153
 
147
154
  /* Define groups which will be used by items */
148
155
  groups?: GroupValue[];
149
156
 
150
157
  /* Overwrite default texts */
151
- texts?: PartialMessages;
158
+ texts?: PartialMessages | null;
152
159
 
153
160
  /* Keep this component open if another Selectic component opens */
154
161
  keepOpenWithOtherSelectic?: boolean;
@@ -157,10 +164,24 @@ export interface Props {
157
164
  params?: SelecticStoreStateParams;
158
165
 
159
166
  /* Method to call to fetch extra data */
160
- fetchCallback?: FetchCallback;
167
+ fetchCallback?: FetchCallback | null;
161
168
 
162
169
  /* Method to call to get specific item */
163
- getItemsCallback?: GetCallback;
170
+ getItemsCallback?: GetCallback | null;
171
+ }
172
+
173
+ type InternalProps = MandateProps<Props>;
174
+
175
+ export interface Data {
176
+ /* Number of items displayed in a page (before scrolling) */
177
+ itemsPerPage: number;
178
+
179
+ labels: Messages;
180
+ /* used to avoid checking and updating table while doing batch stuff */
181
+ doNotUpdate: boolean;
182
+ cacheItem: Map<OptionId, OptionValue>;
183
+ activeOrder: OptionBehaviorOrder;
184
+ dynOffset: number;
164
185
  }
165
186
 
166
187
  export interface SelecticStoreState {
@@ -191,7 +212,7 @@ export interface SelecticStoreState {
191
212
  allowRevert?: boolean;
192
213
 
193
214
  /* If true, user can clear current selection
194
- * (if false, it is still possible to clear it programatically) */
215
+ * (if false, it is still possible to clear it programmatically) */
195
216
  allowClearSelection: boolean;
196
217
 
197
218
  /* If false, do not select the first available option even if value is mandatory */
@@ -298,6 +319,7 @@ interface Messages {
298
319
  export type PartialMessages = { [K in keyof Messages]?: Messages[K] };
299
320
 
300
321
  /* }}} */
322
+ /* {{{ Helper */
301
323
 
302
324
  /**
303
325
  * Escape search string to consider regexp special characters as they
@@ -317,6 +339,30 @@ function convertToRegExp(name: string, flag = 'i'): RegExp {
317
339
  return new RegExp(pattern, flag);
318
340
  }
319
341
 
342
+ /** Does the same as Object.assign but does not replace if value is undefined */
343
+ function assignObject<T>(obj: Partial<T>, ...sourceObjects: Array<Partial<T>>): T {
344
+ const result = obj;
345
+ for (const source of sourceObjects) {
346
+ for (const key of Object.keys(source)) {
347
+ const value = source[key as keyof T];
348
+ if (value === undefined) {
349
+ continue;
350
+ }
351
+ result[key as keyof T] = value;
352
+ }
353
+ }
354
+ return result as T;
355
+ }
356
+
357
+ /* }}} */
358
+ /* {{{ Static */
359
+
360
+ export function changeTexts(texts: PartialMessages) {
361
+ messages = Object.assign(messages, texts);
362
+ }
363
+
364
+ /* }}} */
365
+
320
366
  let messages: Messages = {
321
367
  noFetchMethod: 'Fetch callback is missing: it is not possible to retrieve data.',
322
368
  searchPlaceholder: 'Search',
@@ -338,58 +384,16 @@ let messages: Messages = {
338
384
 
339
385
  let closePreviousSelectic: undefined | voidCaller;
340
386
 
341
- /* {{{ Static */
342
-
343
- export function changeTexts(texts: PartialMessages) {
344
- messages = Object.assign(messages, texts);
345
- }
346
-
347
387
  /* }}} */
348
388
 
349
- @Component
350
- export default class SelecticStore extends Vue<Props> {
351
- /* {{{ props */
352
-
353
- @Prop()
354
- public value?: SelectedValue;
355
-
356
- @Prop({default: false})
357
- public selectionIsExcluded: boolean;
358
-
359
- @Prop({default: false})
360
- public disabled: boolean;
361
-
362
- @Prop()
363
- public options?: OptionProp[];
364
-
365
- @Prop()
366
- public childOptions?: OptionValue[];
367
-
368
- @Prop({default: () => []})
369
- public groups: GroupValue[];
370
-
371
- @Prop()
372
- public texts?: PartialMessages;
373
-
374
- @Prop()
375
- private params?: SelecticStoreStateParams;
376
-
377
- @Prop()
378
- private fetchCallback?: FetchCallback;
389
+ let uid = 0;
379
390
 
380
- @Prop()
381
- private getItemsCallback?: GetCallback;
391
+ export default class SelecticStore {
392
+ public props: InternalProps;
382
393
 
383
- @Prop({ default: false })
384
- private keepOpenWithOtherSelectic: boolean;
385
-
386
- /* }}} */
387
394
  /* {{{ data */
388
395
 
389
- /* Number of items displayed in a page (before scrolling) */
390
- public itemsPerPage = 10;
391
-
392
- public state: SelecticStoreState = {
396
+ public state = reactive<SelecticStoreState>({
393
397
  multiple: false,
394
398
  disabled: false,
395
399
  placeholder: '',
@@ -427,58 +431,216 @@ export default class SelecticStore extends Vue<Props> {
427
431
  areAllSelected: false,
428
432
  hasChanged: false,
429
433
  },
430
- };
431
- public labels = Object.assign({}, messages);
432
- /* used to avoid checking and updating table while doing batch stuff */
433
- private doNotUpdate = false;
434
- private cacheItem: Map<OptionId, OptionValue> = new Map();
435
- private activeOrder: OptionBehaviorOrder = 'D';
436
- private dynOffset: number = 0;
434
+ });
435
+ public data: Data;
437
436
 
438
437
  /* Do not need reactivity */
439
- private requestId: number;
438
+ private requestId: number = 0;
440
439
  private cacheRequest: Map<string, Promise<OptionValue[]>>;
440
+ private closeSelectic: () => void;
441
441
 
442
442
  /* }}} */
443
443
  /* {{{ computed */
444
444
 
445
445
  /* Number of item to pre-display */
446
- get marginSize() {
447
- return this.state.pageSize / 2;
448
- }
446
+ public marginSize: ComputedRef<number>;
449
447
 
450
- get isPartial(): boolean {
451
- const state = this.state;
452
- let isPartial = typeof this.fetchCallback === 'function';
448
+ public isPartial: ComputedRef<boolean>;
449
+ public hasAllItems: ComputedRef<boolean>;
450
+ public hasFetchedAllItems: ComputedRef<boolean>;
451
+ private listOptions: ComputedRef<OptionValue[]>;
452
+ private elementOptions: ComputedRef<OptionValue[]>;
453
+
454
+ /* }}} */
455
+
456
+ public _uid: number; /* Mainly for debugging */
457
+
458
+ constructor(props: Props = {}) {
459
+ this._uid = ++uid;
460
+
461
+ /* {{{ Props */
462
+
463
+ const defaultProps: InternalProps = {
464
+ value: null,
465
+ selectionIsExcluded: false,
466
+ disabled: false,
467
+ options: null,
468
+ childOptions: [],
469
+ groups: [],
470
+ texts: null,
471
+ params: {},
472
+ fetchCallback: null,
473
+ getItemsCallback: null,
474
+ keepOpenWithOtherSelectic: false,
475
+ };
476
+ const propsVal: InternalProps = assignObject(defaultProps, props);
477
+ this.props = reactive(propsVal);
478
+
479
+ /* }}} */
480
+ /* {{{ data */
481
+
482
+ this.data = reactive({
483
+ labels: Object.assign({}, messages),
484
+ itemsPerPage: 10,
485
+ doNotUpdate: false,
486
+ cacheItem: new Map(),
487
+ activeOrder: 'D',
488
+ dynOffset: 0,
489
+ });
453
490
 
454
- if (isPartial && state.optionBehaviorOperation === 'force' && this.activeOrder !== 'D') {
455
- isPartial = false;
491
+ /* }}} */
492
+ /* {{{ computed */
493
+
494
+ this.marginSize = computed(() => {
495
+ return this.state.pageSize / 2;
496
+ });
497
+
498
+ this.isPartial = computed(() => {
499
+ const state = this.state;
500
+ let isPartial = typeof this.props.fetchCallback === 'function';
501
+
502
+ if (isPartial &&
503
+ state.optionBehaviorOperation === 'force' &&
504
+ this.data.activeOrder !== 'D'
505
+ ) {
506
+ isPartial = false;
507
+ }
508
+
509
+ return isPartial;
510
+ });
511
+
512
+ this.hasAllItems = computed(() => {
513
+ const state = this.state;
514
+ const nbItems = state.totalFilteredOptions + state.groups.size;
515
+
516
+ return this.state.filteredOptions.length >= nbItems;
517
+ });
518
+
519
+ this.hasFetchedAllItems = computed(() => {
520
+ const isPartial = this.isPartial.value ?? this.isPartial;
521
+
522
+ if (!isPartial) {
523
+ return true;
524
+ }
525
+ const state = this.state;
526
+
527
+ return state.dynOptions.length === state.totalDynOptions;
528
+ });
529
+
530
+ this.listOptions = computed(() => {
531
+ return this.getListOptions();
532
+ });
533
+
534
+ this.elementOptions = computed(() => {
535
+ return this.getElementOptions();
536
+ });
537
+
538
+ /* }}} */
539
+ /* {{{ watch */
540
+
541
+ watch(() => [this.props.options, this.props.childOptions], () => {
542
+ this.data.cacheItem.clear();
543
+ this.commit('isOpen', false);
544
+ this.buildAllOptions(true);
545
+ this.buildSelectedOptions();
546
+ });
547
+
548
+ watch(() => [this.listOptions, this.elementOptions], () => {
549
+ /* TODO: transform allOptions as a computed properties and this
550
+ * watcher become useless */
551
+ this.buildAllOptions(true);
552
+ });
553
+
554
+ watch(() => this.props.value, () => {
555
+ const value = this.props.value ?? null;
556
+ this.commit('internalValue', value);
557
+ });
558
+
559
+ watch(() => this.props.selectionIsExcluded, () => {
560
+ this.commit('selectionIsExcluded', this.props.selectionIsExcluded);
561
+ });
562
+
563
+ watch(() => this.props.disabled, () => {
564
+ this.commit('disabled', this.props.disabled);
565
+ });
566
+
567
+ watch(() => this.state.filteredOptions, () => {
568
+ let areAllSelected = false;
569
+ const hasAllItems = this.hasAllItems.value ?? this.hasAllItems;
570
+
571
+ if (hasAllItems) {
572
+ const selectionIsExcluded = +this.state.selectionIsExcluded;
573
+ /* eslint-disable-next-line no-bitwise */
574
+ areAllSelected = this.state.filteredOptions.every((item) =>
575
+ !!(+item.selected ^ selectionIsExcluded));
576
+ }
577
+
578
+ this.state.status.areAllSelected = areAllSelected;
579
+ });
580
+
581
+ watch(() => this.state.internalValue, () => {
582
+ this.buildSelectedOptions();
583
+ });
584
+
585
+ watch(() => this.state.allOptions, () => {
586
+ this.checkAutoSelect();
587
+ this.checkAutoDisabled();
588
+ });
589
+
590
+ watch(() => this.state.totalAllOptions, () => {
591
+ this.checkHideFilter();
592
+ });
593
+
594
+ /* }}} */
595
+
596
+ this.closeSelectic = () => {
597
+ this.commit('isOpen', false);
456
598
  }
457
599
 
458
- return isPartial;
459
- }
600
+ const value = this.props.value;
460
601
 
461
- get hasAllItems() {
462
- const nbItems = this.state.totalFilteredOptions + this.state.groups.size;
602
+ /* set initial value for non reactive attribute */
603
+ this.cacheRequest = new Map();
463
604
 
464
- return this.state.filteredOptions.length >= nbItems;
465
- }
605
+ const stateParam: SelecticStoreStateParams | SelecticStoreState =
606
+ Object.assign({}, this.props.params);
466
607
 
467
- get hasFetchedAllItems() {
468
- const state = this.state;
608
+ if (stateParam.optionBehavior) {
609
+ this.buildOptionBehavior(
610
+ stateParam.optionBehavior,
611
+ stateParam as SelecticStoreState
612
+ );
613
+ delete stateParam.optionBehavior;
614
+ }
469
615
 
470
- if (!this.isPartial) {
471
- return true;
616
+ if (stateParam.hideFilter === 'auto') {
617
+ delete stateParam.hideFilter;
472
618
  }
473
619
 
474
- return state.dynOptions.length === state.totalDynOptions;
475
- }
620
+ /* Update state */
621
+ assignObject(this.state, stateParam as SelecticStoreState);
622
+ /* XXX: should be done in 2 lines, in order to set the multiple state
623
+ * and ensure convertValue run with correct state */
624
+ assignObject(this.state, {
625
+ internalValue: this.convertTypeValue(value),
626
+ selectionIsExcluded: props.selectionIsExcluded,
627
+ disabled: props.disabled,
628
+ });
629
+
630
+ this.checkHideFilter();
631
+
632
+ if (this.props.texts) {
633
+ this.changeTexts(this.props.texts);
634
+ }
635
+
636
+ this.addGroups(this.props.groups);
637
+ this.assertValueType();
638
+ this.buildAllOptions();
476
639
 
477
- get closeSelectic() {
478
- return () => this.commit('isOpen', false);
640
+ this.buildSelectedOptions();
641
+ this.checkAutoDisabled();
479
642
  }
480
643
 
481
- /* }}} */
482
644
  /* {{{ methods */
483
645
  /* {{{ public methods */
484
646
 
@@ -524,7 +686,7 @@ export default class SelecticStore extends Vue<Props> {
524
686
  if (typeof closePreviousSelectic === 'function') {
525
687
  closePreviousSelectic();
526
688
  }
527
- if (!this.keepOpenWithOtherSelectic) {
689
+ if (!this.props.keepOpenWithOtherSelectic) {
528
690
  closePreviousSelectic = this.closeSelectic;
529
691
  }
530
692
  }
@@ -553,7 +715,7 @@ export default class SelecticStore extends Vue<Props> {
553
715
  let item: OptionValue;
554
716
 
555
717
  if (this.hasItemInStore(id)) {
556
- item = this.cacheItem.get(id) as OptionValue;
718
+ item = this.data.cacheItem.get(id) as OptionValue;
557
719
  } else {
558
720
  this.getItems([id]);
559
721
  item = {
@@ -567,8 +729,9 @@ export default class SelecticStore extends Vue<Props> {
567
729
 
568
730
  public async getItems(ids: OptionId[]): Promise<OptionItem[]> {
569
731
  const itemsToFetch: OptionId[] = ids.filter((id) => !this.hasItemInStore(id));
732
+ const getItemsCallback = this.props.getItemsCallback;
570
733
 
571
- if (itemsToFetch.length && typeof this.getItemsCallback === 'function') {
734
+ if (itemsToFetch.length && typeof getItemsCallback === 'function') {
572
735
  const cacheRequest = this.cacheRequest;
573
736
  const requestId = itemsToFetch.toString();
574
737
  let promise: Promise<OptionValue[]>;
@@ -576,7 +739,7 @@ export default class SelecticStore extends Vue<Props> {
576
739
  if (cacheRequest.has(requestId)) {
577
740
  promise = cacheRequest.get(requestId)!;
578
741
  } else {
579
- promise = this.getItemsCallback(itemsToFetch);
742
+ promise = getItemsCallback(itemsToFetch);
580
743
  cacheRequest.set(requestId, promise);
581
744
  promise.then(() => {
582
745
  cacheRequest.delete(requestId);
@@ -584,10 +747,11 @@ export default class SelecticStore extends Vue<Props> {
584
747
  }
585
748
 
586
749
  const items = await promise;
750
+ const cacheItem = this.data.cacheItem;
587
751
 
588
752
  for (const item of items) {
589
753
  if (item) {
590
- this.cacheItem.set(item.id, item);
754
+ cacheItem.set(item.id, item);
591
755
  }
592
756
  }
593
757
  }
@@ -598,9 +762,10 @@ export default class SelecticStore extends Vue<Props> {
598
762
  public selectItem(id: OptionId, selected?: boolean, keepOpen = false) {
599
763
  const state = this.state;
600
764
  let hasChanged = false;
765
+ const isPartial = this.isPartial.value ?? this.isPartial;
601
766
 
602
767
  /* Check that item is not disabled */
603
- if (!this.isPartial) {
768
+ if (!isPartial) {
604
769
  const item = state.allOptions.find((opt) => opt.id === id);
605
770
  if (item && item.disabled) {
606
771
  return;
@@ -672,15 +837,18 @@ export default class SelecticStore extends Vue<Props> {
672
837
  if (!this.state.multiple) {
673
838
  return;
674
839
  }
840
+ const hasAllItems = this.hasAllItems.value ?? this.hasAllItems;
841
+
842
+ if (!hasAllItems) {
843
+ const labels = this.data.labels;
675
844
 
676
- if (!this.hasAllItems) {
677
845
  if (this.state.searchText) {
678
- this.state.status.errorMessage = this.labels.cannotSelectAllSearchedItems;
846
+ this.state.status.errorMessage = labels.cannotSelectAllSearchedItems;
679
847
  return;
680
848
  }
681
849
 
682
850
  if (!this.state.allowRevert) {
683
- this.state.status.errorMessage = this.labels.cannotSelectAllRevertItems;
851
+ this.state.status.errorMessage = labels.cannotSelectAllRevertItems;
684
852
  return;
685
853
  }
686
854
 
@@ -695,9 +863,9 @@ export default class SelecticStore extends Vue<Props> {
695
863
 
696
864
  const selectAll = !this.state.status.areAllSelected;
697
865
  this.state.status.areAllSelected = selectAll;
698
- this.doNotUpdate = true;
866
+ this.data.doNotUpdate = true;
699
867
  this.state.filteredOptions.forEach((item) => this.selectItem(item.id, selectAll));
700
- this.doNotUpdate = false;
868
+ this.data.doNotUpdate = false;
701
869
  this.updateFilteredOptions();
702
870
  }
703
871
 
@@ -710,9 +878,10 @@ export default class SelecticStore extends Vue<Props> {
710
878
  }
711
879
 
712
880
  public clearCache(forceReset = false) {
713
- const total = this.isPartial ? Infinity : 0;
881
+ const isPartial = this.isPartial.value ?? this.isPartial;
882
+ const total = isPartial ? Infinity : 0;
714
883
 
715
- this.cacheItem.clear();
884
+ this.data.cacheItem.clear();
716
885
 
717
886
  this.state.allOptions = [];
718
887
  this.state.totalAllOptions = total;
@@ -746,7 +915,7 @@ export default class SelecticStore extends Vue<Props> {
746
915
  }
747
916
 
748
917
  public changeTexts(texts: PartialMessages) {
749
- this.labels = Object.assign({}, this.labels, texts);
918
+ this.data.labels = Object.assign({}, this.data.labels, texts);
750
919
  }
751
920
 
752
921
  /* }}} */
@@ -767,25 +936,52 @@ export default class SelecticStore extends Vue<Props> {
767
936
 
768
937
  return this.state.filteredOptions.find(findId) ||
769
938
  this.state.dynOptions.find(findId) ||
770
- this.getListOptions().find(findId) ||
771
- this.getElementOptions().find(findId);
939
+ (this.listOptions.value ?? this.listOptions).find(findId) ||
940
+ (this.elementOptions.value ?? this.elementOptions).find(findId);
941
+ }
942
+
943
+ private convertTypeValue(oldValue: OptionId | StrictOptionId[]) {
944
+ const state = this.state;
945
+ const isMultiple = state.multiple;
946
+ let newValue = oldValue;
947
+
948
+ if (isMultiple) {
949
+ if (!Array.isArray(oldValue)) {
950
+ newValue = oldValue === null ? [] : [oldValue];
951
+ }
952
+ } else {
953
+ if (Array.isArray(oldValue)) {
954
+ const value = oldValue[0];
955
+ newValue = typeof value === 'undefined' ? null : value;
956
+ }
957
+ }
958
+ return newValue;
772
959
  }
773
960
 
774
- private assertCorrectValue(forceStrict = false) {
961
+ private assertValueType() {
775
962
  const state = this.state;
776
963
  const internalValue = state.internalValue;
964
+ const newValue = this.convertTypeValue(internalValue);
965
+
966
+ if (newValue !== internalValue) {
967
+ state.internalValue = newValue;
968
+ }
969
+ }
970
+
971
+ private assertCorrectValue(applyStrict = false) {
972
+ const state = this.state;
973
+ this.assertValueType();
974
+ const internalValue = state.internalValue;
777
975
  const selectionIsExcluded = state.selectionIsExcluded;
778
976
  const isMultiple = state.multiple;
779
977
  const checkStrict = state.strictValue;
780
978
  let newValue = internalValue;
781
- const isPartial = this.isPartial;
979
+ const isPartial = this.isPartial.value ?? this.isPartial;
782
980
 
783
981
  if (isMultiple) {
784
- if (!Array.isArray(internalValue)) {
785
- newValue = internalValue === null ? [] : [internalValue];
786
- }
982
+ const hasFetchedAllItems = this.hasFetchedAllItems.value ?? this.hasFetchedAllItems;
787
983
 
788
- if (selectionIsExcluded && this.hasFetchedAllItems) {
984
+ if (selectionIsExcluded && hasFetchedAllItems) {
789
985
  newValue = state.allOptions.reduce((values, option) => {
790
986
  const id = option.id as StrictOptionId;
791
987
 
@@ -798,11 +994,6 @@ export default class SelecticStore extends Vue<Props> {
798
994
  state.selectionIsExcluded = false;
799
995
  }
800
996
  } else {
801
- if (Array.isArray(internalValue)) {
802
- const value = internalValue[0];
803
- newValue = typeof value === 'undefined' ? null : value;
804
- }
805
-
806
997
  state.selectionIsExcluded = false;
807
998
  }
808
999
 
@@ -815,17 +1006,19 @@ export default class SelecticStore extends Vue<Props> {
815
1006
  .filter((value) => this.hasItemInStore(value));
816
1007
  isDifferent = filteredValue.length !== (newValue as StrictOptionId[]).length;
817
1008
 
818
- if (isDifferent && isPartial && !forceStrict) {
819
- this.getItems(newValue as StrictOptionId[]).then(() => this.assertCorrectValue(true));
1009
+ if (isDifferent && isPartial && !applyStrict) {
1010
+ this.getItems(newValue as StrictOptionId[])
1011
+ .then(() => this.assertCorrectValue(true));
820
1012
  return;
821
1013
  }
822
1014
  } else
823
- if (!this.hasItemInStore(newValue as OptionId)) {
1015
+ if (newValue !== null && !this.hasItemInStore(newValue as OptionId)) {
824
1016
  filteredValue = null;
825
1017
  isDifferent = true;
826
1018
 
827
- if (isPartial && !forceStrict) {
828
- this.getItems([newValue as OptionId]).then(() => this.assertCorrectValue(true));
1019
+ if (isPartial && !applyStrict) {
1020
+ this.getItems([newValue as OptionId])
1021
+ .then(() => this.assertCorrectValue(true));
829
1022
  return;
830
1023
  }
831
1024
  }
@@ -843,8 +1036,9 @@ export default class SelecticStore extends Vue<Props> {
843
1036
  }
844
1037
 
845
1038
  private updateFilteredOptions() {
846
- if (!this.doNotUpdate) {
1039
+ if (!this.data.doNotUpdate) {
847
1040
  this.state.filteredOptions = this.buildItems(this.state.filteredOptions);
1041
+ this.buildSelectedOptions();
848
1042
  }
849
1043
  }
850
1044
 
@@ -854,14 +1048,15 @@ export default class SelecticStore extends Vue<Props> {
854
1048
  });
855
1049
  }
856
1050
 
857
- /* XXX: This is not a computed property to avoid consuming more memory */
1051
+ /* This method is for the computed property listOptions */
858
1052
  private getListOptions(): OptionValue[] {
859
- const options = this.options;
1053
+ const options = this.props.options;
860
1054
  const listOptions: OptionValue[] = [];
861
1055
 
862
1056
  if (!Array.isArray(options)) {
863
1057
  return listOptions;
864
1058
  }
1059
+ const state = this.state;
865
1060
 
866
1061
  options.forEach((option) => {
867
1062
  /* manage simple string */
@@ -877,14 +1072,14 @@ export default class SelecticStore extends Vue<Props> {
877
1072
  const subOptions = option.options;
878
1073
 
879
1074
  /* check for groups */
880
- if (group && !this.state.groups.has(group)) {
881
- this.state.groups.set(group, String(group));
1075
+ if (group && !state.groups.has(group)) {
1076
+ state.groups.set(group, String(group));
882
1077
  }
883
1078
 
884
1079
  /* check for sub options */
885
1080
  if (subOptions) {
886
1081
  const groupId = option.id as StrictOptionId;
887
- this.state.groups.set(groupId, option.text);
1082
+ state.groups.set(groupId, option.text);
888
1083
 
889
1084
  subOptions.forEach((subOpt) => {
890
1085
  subOpt.group = groupId;
@@ -899,28 +1094,29 @@ export default class SelecticStore extends Vue<Props> {
899
1094
  return listOptions;
900
1095
  }
901
1096
 
902
- /* XXX: This is not a computed property to avoid consuming more memory */
1097
+ /* This method is for the computed property elementOptions */
903
1098
  private getElementOptions(): OptionValue[] {
904
- const options = this.childOptions;
1099
+ const options = this.props.childOptions;
905
1100
  const childOptions: OptionValue[] = [];
906
1101
 
907
- if (!Array.isArray(options)) {
1102
+ if (!Array.isArray(options) || options.length === 0) {
908
1103
  return childOptions;
909
1104
  }
1105
+ const state = this.state;
910
1106
 
911
1107
  options.forEach((option) => {
912
1108
  const group = option.group;
913
1109
  const subOptions = option.options;
914
1110
 
915
1111
  /* check for groups */
916
- if (group && !this.state.groups.has(group)) {
917
- this.state.groups.set(group, String(group));
1112
+ if (group && !state.groups.has(group)) {
1113
+ state.groups.set(group, String(group));
918
1114
  }
919
1115
 
920
1116
  /* check for sub options */
921
1117
  if (subOptions) {
922
1118
  const groupId = option.id as StrictOptionId;
923
- this.state.groups.set(groupId, option.text);
1119
+ state.groups.set(groupId, option.text);
924
1120
 
925
1121
  const sOpts: OptionValue[] = subOptions.map((subOpt) => {
926
1122
  return Object.assign({}, subOpt, {
@@ -943,6 +1139,7 @@ export default class SelecticStore extends Vue<Props> {
943
1139
  let elementOptions: OptionValue[] = [];
944
1140
  const optionBehaviorOrder = this.state.optionBehaviorOrder;
945
1141
  let length: number = Infinity;
1142
+ const isPartial = this.isPartial.value ?? this.isPartial;
946
1143
 
947
1144
  const arrayFromOrder = (orderValue: OptionBehaviorOrder): OptionValue[] => {
948
1145
  switch(orderValue) {
@@ -963,7 +1160,7 @@ export default class SelecticStore extends Vue<Props> {
963
1160
  };
964
1161
 
965
1162
  if (!keepFetched) {
966
- if (this.isPartial) {
1163
+ if (isPartial) {
967
1164
  this.state.totalAllOptions = Infinity;
968
1165
  this.state.totalDynOptions = Infinity;
969
1166
  } else {
@@ -971,15 +1168,15 @@ export default class SelecticStore extends Vue<Props> {
971
1168
  }
972
1169
  }
973
1170
 
974
- listOptions = this.getListOptions();
975
- elementOptions = this.getElementOptions();
1171
+ listOptions = this.listOptions.value ?? this.listOptions;
1172
+ elementOptions = this.elementOptions.value ?? this.elementOptions;
976
1173
 
977
1174
  if (this.state.optionBehaviorOperation === 'force') {
978
1175
  const orderValue = optionBehaviorOrder.find((value) => lengthFromOrder(value) > 0)!;
979
1176
  allOptions.push(...arrayFromOrder(orderValue));
980
1177
  length = lengthFromOrder(orderValue);
981
- this.activeOrder = orderValue;
982
- this.dynOffset = 0;
1178
+ this.data.activeOrder = orderValue;
1179
+ this.data.dynOffset = 0;
983
1180
  } else {
984
1181
  /* sort */
985
1182
  let offset = 0;
@@ -988,7 +1185,7 @@ export default class SelecticStore extends Vue<Props> {
988
1185
  const lngth = lengthFromOrder(orderValue);
989
1186
 
990
1187
  if (orderValue === 'D') {
991
- this.dynOffset = offset;
1188
+ this.data.dynOffset = offset;
992
1189
  } else {
993
1190
  offset += lngth;
994
1191
  }
@@ -999,7 +1196,7 @@ export default class SelecticStore extends Vue<Props> {
999
1196
  break;
1000
1197
  }
1001
1198
  }
1002
- this.activeOrder = 'D';
1199
+ this.data.activeOrder = 'D';
1003
1200
  length = optionBehaviorOrder.reduce((total, orderValue) => total + lengthFromOrder(orderValue), 0);
1004
1201
  }
1005
1202
 
@@ -1008,7 +1205,7 @@ export default class SelecticStore extends Vue<Props> {
1008
1205
  if (keepFetched) {
1009
1206
  this.state.totalAllOptions = length;
1010
1207
  } else {
1011
- if (!this.isPartial) {
1208
+ if (!isPartial) {
1012
1209
  this.state.totalAllOptions = allOptions.length;
1013
1210
  }
1014
1211
  }
@@ -1016,7 +1213,10 @@ export default class SelecticStore extends Vue<Props> {
1016
1213
  this.state.filteredOptions = [];
1017
1214
  this.state.totalFilteredOptions = Infinity;
1018
1215
 
1019
- this.buildFilteredOptions();
1216
+ this.buildFilteredOptions().then(() => {
1217
+ /* XXX: To recompute for strict mode and auto-select */
1218
+ this.assertCorrectValue();
1219
+ });
1020
1220
  }
1021
1221
 
1022
1222
  private async buildFilteredOptions() {
@@ -1030,14 +1230,16 @@ export default class SelecticStore extends Vue<Props> {
1030
1230
  const totalAllOptions = this.state.totalAllOptions;
1031
1231
  const allOptionsLength = allOptions.length;
1032
1232
  let filteredOptionsLength = this.state.filteredOptions.length;
1233
+ const hasAllItems = this.hasAllItems.value ?? this.hasAllItems;
1033
1234
 
1034
- if (this.hasAllItems) {
1235
+ if (hasAllItems) {
1035
1236
  /* Everything has already been fetched and stored in filteredOptions */
1036
1237
  return;
1037
1238
  }
1038
1239
 
1240
+ const hasFetchedAllItems = this.hasFetchedAllItems.value ?? this.hasFetchedAllItems;
1039
1241
  /* Check if all options have been fetched */
1040
- if (this.hasFetchedAllItems) {
1242
+ if (hasFetchedAllItems) {
1041
1243
  if (!search) {
1042
1244
  this.state.filteredOptions = this.buildGroupItems(allOptions);
1043
1245
  this.state.totalFilteredOptions = this.state.filteredOptions.length;
@@ -1053,7 +1255,7 @@ export default class SelecticStore extends Vue<Props> {
1053
1255
  /* When we only have partial options */
1054
1256
 
1055
1257
  const offsetItem = this.state.offsetItem;
1056
- const marginSize = this.marginSize;
1258
+ const marginSize = this.marginSize.value ?? this.marginSize;
1057
1259
  const endIndex = offsetItem + marginSize;
1058
1260
 
1059
1261
  if (endIndex <= filteredOptionsLength) {
@@ -1063,7 +1265,8 @@ export default class SelecticStore extends Vue<Props> {
1063
1265
  if (!search && endIndex <= allOptionsLength) {
1064
1266
  this.state.filteredOptions = this.buildGroupItems(allOptions);
1065
1267
  this.state.totalFilteredOptions = totalAllOptions + this.state.groups.size;
1066
- if (this.isPartial && this.state.totalDynOptions === Infinity) {
1268
+ const isPartial = this.isPartial.value ?? this.isPartial;
1269
+ if (isPartial && this.state.totalDynOptions === Infinity) {
1067
1270
  this.fetchData();
1068
1271
  }
1069
1272
  return;
@@ -1073,7 +1276,7 @@ export default class SelecticStore extends Vue<Props> {
1073
1276
  this.addStaticFilteredOptions();
1074
1277
 
1075
1278
  filteredOptionsLength = this.state.filteredOptions.length;
1076
- this.dynOffset = filteredOptionsLength;
1279
+ this.data.dynOffset = filteredOptionsLength;
1077
1280
  if (endIndex <= filteredOptionsLength) {
1078
1281
  return;
1079
1282
  }
@@ -1084,26 +1287,27 @@ export default class SelecticStore extends Vue<Props> {
1084
1287
 
1085
1288
  private async buildSelectedOptions() {
1086
1289
  const internalValue = this.state.internalValue;
1290
+ const state = this.state;
1087
1291
 
1088
- if (this.state.multiple) {
1292
+ if (state.multiple) {
1089
1293
  /* display partial information about selected items */
1090
- this.state.selectedOptions = this.buildSelectedItems(internalValue as StrictOptionId[]);
1294
+ state.selectedOptions = this.buildSelectedItems(internalValue as StrictOptionId[]);
1091
1295
 
1092
1296
  const items: OptionItem[] = await this.getItems(internalValue as StrictOptionId[]).catch(() => []);
1093
- if (internalValue !== this.state.internalValue) {
1297
+ if (internalValue !== state.internalValue) {
1094
1298
  /* Values have been deprecated */
1095
1299
  return;
1096
1300
  }
1097
1301
 
1098
1302
  if (items.length !== (internalValue as StrictOptionId[]).length) {
1099
- if (!this.state.strictValue) {
1100
- const updatedItems = this.state.selectedOptions.map((option) => {
1303
+ if (!state.strictValue) {
1304
+ const updatedItems = state.selectedOptions.map((option) => {
1101
1305
  const foundItem = items.find((item) => item.id === option.id);
1102
1306
 
1103
1307
  return foundItem || option;
1104
1308
  });
1105
1309
 
1106
- this.state.selectedOptions = updatedItems;
1310
+ state.selectedOptions = updatedItems;
1107
1311
  } else {
1108
1312
  const itemIds = items.map((item) => item.id as StrictOptionId) ;
1109
1313
 
@@ -1113,37 +1317,39 @@ export default class SelecticStore extends Vue<Props> {
1113
1317
  }
1114
1318
 
1115
1319
  /* display full information about selected items */
1116
- this.state.selectedOptions = items;
1320
+ state.selectedOptions = items;
1117
1321
  } else
1118
1322
  if (internalValue === null) {
1119
- this.state.selectedOptions = null;
1323
+ state.selectedOptions = null;
1120
1324
  } else {
1121
1325
  /* display partial information about selected items */
1122
- this.state.selectedOptions = this.buildSelectedItems([internalValue as OptionId])[0];
1326
+ state.selectedOptions = this.buildSelectedItems([internalValue as OptionId])[0];
1123
1327
 
1124
1328
  const items = await this.getItems([internalValue as OptionId]).catch(() => []);
1125
- if (internalValue !== this.state.internalValue) {
1329
+ if (internalValue !== state.internalValue) {
1126
1330
  /* Values have been deprecated */
1127
1331
  return;
1128
1332
  }
1129
1333
 
1130
1334
  if (!items.length) {
1131
- if (this.state.strictValue) {
1335
+ if (state.strictValue) {
1132
1336
  this.commit('internalValue', null);
1133
1337
  }
1134
1338
  return;
1135
1339
  }
1136
1340
 
1137
1341
  /* display full information about selected items */
1138
- this.state.selectedOptions = items[0];
1342
+ state.selectedOptions = items[0];
1139
1343
  }
1140
1344
  }
1141
1345
 
1142
1346
  private async fetchData() {
1143
1347
  const state = this.state;
1348
+ const labels = this.data.labels;
1349
+ const fetchCallback = this.props.fetchCallback;
1144
1350
 
1145
- if (!this.fetchCallback) {
1146
- state.status.errorMessage = this.labels.noFetchMethod;
1351
+ if (!fetchCallback) {
1352
+ state.status.errorMessage = labels.noFetchMethod;
1147
1353
  return;
1148
1354
  }
1149
1355
 
@@ -1151,25 +1357,26 @@ export default class SelecticStore extends Vue<Props> {
1151
1357
  const filteredOptionsLength = state.filteredOptions.length;
1152
1358
  const offsetItem = state.offsetItem;
1153
1359
  const pageSize = state.pageSize;
1154
- const marginSize = this.marginSize;
1360
+ const marginSize = this.marginSize.value ?? this.marginSize;
1155
1361
  const endIndex = offsetItem + marginSize;
1362
+ const dynOffset = this.data.dynOffset;
1156
1363
 
1157
1364
  /* Run the query */
1158
1365
  this.state.status.searching = true;
1159
1366
 
1160
1367
  /* Manage cases where offsetItem is not equal to the last item received */
1161
- const offset = filteredOptionsLength - this.nbGroups(state.filteredOptions) - this.dynOffset;
1368
+ const offset = filteredOptionsLength - this.nbGroups(state.filteredOptions) - dynOffset;
1162
1369
  const nbItems = endIndex - offset;
1163
1370
  const limit = Math.ceil(nbItems / pageSize) * pageSize;
1164
1371
 
1165
1372
  try {
1166
1373
  const requestId = ++this.requestId;
1167
- const {total: rTotal, result} = await this.fetchCallback(search, offset, limit);
1374
+ const {total: rTotal, result} = await fetchCallback(search, offset, limit);
1168
1375
  let total = rTotal;
1169
1376
 
1170
1377
  /* Assert result is correctly formatted */
1171
1378
  if (!Array.isArray(result)) {
1172
- throw new Error(this.labels.wrongFormattedData);
1379
+ throw new Error(labels.wrongFormattedData);
1173
1380
  }
1174
1381
 
1175
1382
  /* Handle case where total is not returned */
@@ -1186,7 +1393,7 @@ export default class SelecticStore extends Vue<Props> {
1186
1393
  /* update cache */
1187
1394
  state.totalDynOptions = total;
1188
1395
  state.dynOptions.splice(offset, limit, ...result);
1189
- this.$nextTick(() => this.buildAllOptions(true));
1396
+ setTimeout(() => this.buildAllOptions(true), 0);
1190
1397
  }
1191
1398
 
1192
1399
  /* Check request is not obsolete */
@@ -1201,7 +1408,7 @@ export default class SelecticStore extends Vue<Props> {
1201
1408
  const options = this.buildGroupItems(result, previousItem);
1202
1409
  const nbGroups1 = this.nbGroups(options);
1203
1410
 
1204
- state.filteredOptions.splice(offset + this.dynOffset, limit + nbGroups1, ...options);
1411
+ state.filteredOptions.splice(offset + dynOffset, limit + nbGroups1, ...options);
1205
1412
  }
1206
1413
 
1207
1414
  let nbGroups = state.groups.size;
@@ -1209,7 +1416,7 @@ export default class SelecticStore extends Vue<Props> {
1209
1416
  nbGroups = this.nbGroups(state.filteredOptions);
1210
1417
  }
1211
1418
 
1212
- state.totalFilteredOptions = total + nbGroups + this.dynOffset;
1419
+ state.totalFilteredOptions = total + nbGroups + dynOffset;
1213
1420
 
1214
1421
  if (search && state.totalFilteredOptions <= state.filteredOptions.length) {
1215
1422
  this.addStaticFilteredOptions(true);
@@ -1217,7 +1424,7 @@ export default class SelecticStore extends Vue<Props> {
1217
1424
 
1218
1425
  state.status.errorMessage = '';
1219
1426
  } catch (e) {
1220
- state.status.errorMessage = e.message;
1427
+ state.status.errorMessage = (e as Error).message;
1221
1428
  if (!search) {
1222
1429
  state.totalDynOptions = 0;
1223
1430
  this.buildAllOptions(true);
@@ -1261,10 +1468,10 @@ export default class SelecticStore extends Vue<Props> {
1261
1468
 
1262
1469
  switch (order) {
1263
1470
  case 'O':
1264
- options = this.filterOptions(this.getListOptions(), search);
1471
+ options = this.filterOptions(this.listOptions.value ?? this.listOptions, search);
1265
1472
  break;
1266
1473
  case 'E':
1267
- options = this.filterOptions(this.getElementOptions(), search);
1474
+ options = this.filterOptions(this.elementOptions.value ?? this.elementOptions, search);
1268
1475
  break;
1269
1476
  }
1270
1477
  this.state.filteredOptions.push(...options);
@@ -1274,7 +1481,8 @@ export default class SelecticStore extends Vue<Props> {
1274
1481
 
1275
1482
  private buildSelectedItems(ids: OptionId[]): OptionItem[] {
1276
1483
  return this.buildItems(ids.map((id) => {
1277
- const item = this.cacheItem.get(id);
1484
+ const cacheItem = this.data.cacheItem;
1485
+ const item = cacheItem.get(id);
1278
1486
 
1279
1487
  return item || {
1280
1488
  id,
@@ -1284,13 +1492,14 @@ export default class SelecticStore extends Vue<Props> {
1284
1492
  }
1285
1493
 
1286
1494
  private hasItemInStore(id: OptionId): boolean {
1287
- let item: OptionValue | undefined = this.cacheItem.get(id);
1495
+ const cacheItem = this.data.cacheItem;
1496
+ let item: OptionValue | undefined = cacheItem.get(id);
1288
1497
 
1289
1498
  if (!item) {
1290
1499
  item = this.getValue(id);
1291
1500
 
1292
1501
  if (item) {
1293
- this.cacheItem.set(item.id, item);
1502
+ cacheItem.set(item.id, item);
1294
1503
  }
1295
1504
  }
1296
1505
 
@@ -1311,7 +1520,7 @@ export default class SelecticStore extends Vue<Props> {
1311
1520
  disabled: false,
1312
1521
  isGroup: false,
1313
1522
  }, option, {
1314
- // tslint:disable-next-line:no-bitwise
1523
+ /* eslint-disable-next-line no-bitwise */
1315
1524
  selected: !!(+selected.includes(id) ^ selectionIsExcluded),
1316
1525
  });
1317
1526
  });
@@ -1355,7 +1564,8 @@ export default class SelecticStore extends Vue<Props> {
1355
1564
  isValid = isValid && /^[ODE]+$/.test(order);
1356
1565
 
1357
1566
  if (!isValid) {
1358
- this.state.status.errorMessage = this.labels.unknownPropertyValue.replace(/%s/, 'optionBehavior');
1567
+ const labels = this.data.labels;
1568
+ this.state.status.errorMessage = labels.unknownPropertyValue.replace(/%s/, 'optionBehavior');
1359
1569
  operation = 'sort';
1360
1570
  orderArray = ['O', 'D', 'E'];
1361
1571
  } else {
@@ -1387,6 +1597,7 @@ export default class SelecticStore extends Vue<Props> {
1387
1597
  for (const option of options) {
1388
1598
  if (!option.disabled) {
1389
1599
  this.selectItem(option.id, true, true);
1600
+ this.checkAutoDisabled();
1390
1601
  return;
1391
1602
  }
1392
1603
  }
@@ -1394,9 +1605,11 @@ export default class SelecticStore extends Vue<Props> {
1394
1605
 
1395
1606
  private checkAutoDisabled() {
1396
1607
  const state = this.state;
1397
- const doNotCheck = this.disabled || this.isPartial || !state.autoDisabled;
1608
+ const isPartial = this.isPartial.value ?? this.isPartial;
1609
+ const doNotCheck = isPartial || this.props.disabled || !state.autoDisabled;
1610
+ const hasFetchedAllItems = this.hasFetchedAllItems.value ?? this.hasFetchedAllItems;
1398
1611
 
1399
- if (doNotCheck || !this.hasFetchedAllItems) {
1612
+ if (doNotCheck || !hasFetchedAllItems) {
1400
1613
  return;
1401
1614
  }
1402
1615
 
@@ -1420,128 +1633,22 @@ export default class SelecticStore extends Vue<Props> {
1420
1633
  }
1421
1634
 
1422
1635
  private checkHideFilter() {
1423
- if (this.params && this.params.hideFilter !== 'auto') {
1636
+ const params = this.props.params;
1637
+ if (params && params.hideFilter !== 'auto') {
1424
1638
  return;
1425
1639
  }
1426
1640
 
1427
1641
  const state = this.state;
1642
+ const isPartial = this.isPartial.value ?? this.isPartial;
1428
1643
 
1429
- if (state.multiple || this.isPartial) {
1644
+ if (state.multiple || isPartial) {
1430
1645
  state.hideFilter = false;
1431
1646
  } else {
1432
- state.hideFilter = state.totalAllOptions <= this.itemsPerPage;
1647
+ state.hideFilter = state.totalAllOptions <= this.data.itemsPerPage;
1433
1648
  }
1434
1649
  }
1435
1650
 
1436
1651
  /* }}} */
1437
1652
  /* }}} */
1438
- /* {{{ watch */
1439
-
1440
- @Watch('options')
1441
- protected onOptionsChange(options: OptionValue[] = [], oldOptions: OptionValue[] = []) {
1442
- if (JSON.stringify(options) === JSON.stringify(oldOptions)) {
1443
- /* There is no real difference, only a change of reference */
1444
- return;
1445
- }
1446
- this.cacheItem.clear();
1447
- this.commit('isOpen', false);
1448
- this.buildAllOptions(true);
1449
- this.assertCorrectValue();
1450
- this.buildSelectedOptions();
1451
- }
1452
-
1453
- @Watch('childOptions')
1454
- protected onChildOptionsChange(childOptions: OptionValue[] = [], oldChildOptions: OptionValue[] = []) {
1455
- if (JSON.stringify(childOptions) === JSON.stringify(oldChildOptions)) {
1456
- /* There is no real difference, only a change of reference */
1457
- return;
1458
- }
1459
- this.cacheItem.clear();
1460
- this.commit('isOpen', false);
1461
- this.buildAllOptions(true);
1462
- this.assertCorrectValue();
1463
- this.buildSelectedOptions();
1464
- }
1465
-
1466
- @Watch('value')
1467
- protected onValueChange() {
1468
- const value = typeof this.value === 'undefined' ? null : this.value;
1469
- this.commit('internalValue', value);
1470
- }
1471
-
1472
- @Watch('selectionIsExcluded')
1473
- protected onSelectionExcludedChange() {
1474
- this.commit('selectionIsExcluded', this.selectionIsExcluded);
1475
- }
1476
-
1477
- @Watch('disabled')
1478
- protected onDisabledChange() {
1479
- this.commit('disabled', this.disabled);
1480
- }
1481
-
1482
- @Watch('state.filteredOptions')
1483
- protected onFilteredChange() {
1484
- let areAllSelected = false;
1485
-
1486
- if (this.hasAllItems) {
1487
- const selectionIsExcluded = +this.state.selectionIsExcluded;
1488
- // tslint:disable-next-line:no-bitwise
1489
- areAllSelected = this.state.filteredOptions.every((item) => !!(+item.selected ^ selectionIsExcluded));
1490
- }
1491
-
1492
- this.state.status.areAllSelected = areAllSelected;
1493
- }
1494
-
1495
- @Watch('state.internalValue')
1496
- protected onInternalValueChange() {
1497
- this.buildSelectedOptions();
1498
- }
1499
-
1500
- @Watch('state.allOptions')
1501
- protected onAllOptionChange() {
1502
- this.checkAutoSelect();
1503
- this.checkAutoDisabled();
1504
- }
1505
-
1506
- @Watch('state.totalAllOptions')
1507
- protected onTotalAllOptionsChange() {
1508
- this.checkHideFilter();
1509
- }
1510
-
1511
- /* }}} */
1512
- /* {{{ life cycles methods */
1513
-
1514
- protected created() {
1515
- const value = typeof this.value === 'undefined' ? null : this.value;
1516
-
1517
- /* set initial value for non reactive attribute */
1518
- this.requestId = 0;
1519
- this.cacheRequest = new Map();
1520
-
1521
- const stateParam = Object.assign({}, this.params);
1522
-
1523
- if (stateParam.optionBehavior) {
1524
- this.buildOptionBehavior(stateParam.optionBehavior, stateParam as SelecticStoreState);
1525
- delete stateParam.optionBehavior;
1526
- }
1527
-
1528
- this.state = Object.assign(this.state, stateParam, {
1529
- internalValue: value,
1530
- selectionIsExcluded: this.selectionIsExcluded,
1531
- disabled: this.disabled,
1532
- });
1533
-
1534
- this.checkHideFilter();
1535
1653
 
1536
- if (this.texts) {
1537
- this.changeTexts(this.texts);
1538
- }
1539
-
1540
- this.addGroups(this.groups);
1541
- this.buildAllOptions();
1542
- this.assertCorrectValue();
1543
- this.buildSelectedOptions();
1544
- }
1545
-
1546
- /* }}} */
1547
- }
1654
+ };