diff --git a/README.md b/README.md
index f8ce601..d75cbd4 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,9 @@ Dropdown menu with search and multiple options selection
### Element properties
-
-* allowOutsideScroll - boolean, default: false
-* autoValidate - boolean
+* allowOutsideScroll - Boolean, default: false
+* autoValidate - Boolean
+* capitalizeInputShown - Boolean
* customObjectOptions - Boolean, default: false
* disabled - Boolean, default: false
* dynamicAlign - Boolean, default: false
@@ -19,6 +19,8 @@ Dropdown menu with search and multiple options selection
* menuOpened - Boolean, default: false – notifies
* multi - Boolean, default: false
* noChangeEvent - Boolean, default: false
+* noOptionsAvailable - Boolean, default: false
+* notFoundValues - Array
* optionLabel - String, default: label
* options - Array
* optionValue - String, default: 'value'
@@ -27,6 +29,8 @@ Dropdown menu with search and multiple options selection
* required - boolean
* search - String
* selected - Number/Array - notifies
+* selectedRequiresValidOptions - Boolean, default: false; using this and selected will ensure selected values will
+be set only if the options are not empty
* selectedValues - Object notifies
* showLimitWarning - Boolean
* shownItems - Array
diff --git a/bower.json b/bower.json
index 763558f..83a8f33 100644
--- a/bower.json
+++ b/bower.json
@@ -1,7 +1,7 @@
{
"name": "etools-searchable-multiselection-menu",
"description": "Dropdown menu with search and multiple options selection",
- "version": "1.0.31",
+ "version": "1.0.35",
"license": "https://github.com/unicef-polymer/etools-searchable-multiselection-menu/blob/master/LICENSE.md",
"main": "etools-searchable-multiselection-menu.html",
"dependencies": {
diff --git a/demo/demo-custom-objects-as-options.html b/demo/demo-custom-objects-as-options.html
index 60cebde..f0fa515 100644
--- a/demo/demo-custom-objects-as-options.html
+++ b/demo/demo-custom-objects-as-options.html
@@ -89,9 +89,9 @@
Custom objects as options and selected property with no change events
// this.set('selectedValues', [{value: 2, label: 'Option 2'}]);
// this.set('selectedId', 3);
- setTimeout(function() {
+ //setTimeout(function() {
this.set('customObjOptions', this.generateOptions());
- }.bind(this), 3000);
+ //}.bind(this), 3000);
// setTimeout(function() {
// this.set('selectedIds', null);
diff --git a/demo/index.html b/demo/index.html
index 086da49..4f72605 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -131,7 +131,7 @@ Error messages and validations
-
+
Custom objects as options. You can specify value and label properties from object option to be used.
diff --git a/etools-searchable-multiselection-menu.html b/etools-searchable-multiselection-menu.html
index 58bc840..1ccf227 100644
--- a/etools-searchable-multiselection-menu.html
+++ b/etools-searchable-multiselection-menu.html
@@ -377,7 +377,8 @@
reflectToAttribute: true
},
options: {
- type: Array
+ type: Array,
+ observer: '_optionsChanged'
},
shownItems: {
type: Array,
@@ -459,7 +460,8 @@
value: 'label'
},
selected: {
- notify: true
+ notify: true,
+ observer: '_selectedOptionsChanged'
},
_prevSelectedValues: {
type: Object
@@ -477,10 +479,18 @@
type: Boolean,
reflectToAttribute: true,
},
+ selectedRequiresValidOptions: {
+ type: Boolean,
+ value: false
+ },
+ notFoundValues: {
+ type: Array,
+ notify: true,
+ value: []
+ }
},
observers: [
- '_selectedChanged(selected, options)',
'_optionsLengthChanged(options.length)'
],
@@ -557,8 +567,16 @@
if (this.readonly) {
return;
}
- if(!this.multi) {
+ if (!this.multi) {
this.selectedValues = e.model.item.value;
+
+ if (this.selectedValues === null) {
+ if (this.value === null && this.updateSelected &&
+ this.notFoundValues instanceof Array && this.notFoundValues.length) {
+ this.set('selected', null);
+ }
+ }
+
this._valueSelected();
this.$.dropdownMenu.close();
}
@@ -684,60 +702,86 @@
}
},
- _selectedChanged: function(selected, options) {
- if (!this.updateSelected) {
+ _optionsChanged: function(options) {
+ if (options instanceof Array) {
+ this._selectionChanged(this.selected, options);
+ }
+ },
+
+ _selectedOptionsChanged: function(selected, oldSelected) {
+ if (this.multi && JSON.stringify(selected) === JSON.stringify(oldSelected)) {
return;
}
- var currentValue = null;
- var notFoundValue = [];
- if (this.multi) {
- currentValue = [];
- if (selected instanceof Array && selected.length > 0) {
- if (options instanceof Array && options.length > 0) {
- selected.forEach(function(selectedVal) {
- var s = this._prepareValue(selectedVal);
- notFoundValue.push(s);
- for (var i = 0; i < options.length; i++) {
- if (this._prepareValue(options[i][this.optionValue]) === s) {
- currentValue.push(options[i]);
- notFoundValue.splice(notFoundValue.indexOf(s), 1);
+ this._selectionChanged(selected, this.options);
+ },
+
+ _selectionChanged: function(selected, options) {
+ this.debounce('selectionChanged', function() {
+ if (!this.updateSelected) {
+ return;
+ }
+
+ if (this.selectedRequiresValidOptions &&
+ (options instanceof Array === false ||
+ (options instanceof Array && options.length === 0))) {
+ return;
+ }
+
+ var currentValue = null;
+ var notFoundValues = [];
+ var i;
+ if (this.multi) {
+ // multiple selection
+ currentValue = [];
+ if (selected instanceof Array && selected.length > 0) {
+ notFoundValues = JSON.parse(JSON.stringify(selected));
+ if (options instanceof Array && options.length > 0) {
+ selected.forEach(function(selectedVal) {
+ var s = this._prepareValue(selectedVal);
+ for (i = 0; i < options.length; i++) {
+ if (this._prepareValue(options[i][this.optionValue]) === s) {
+ currentValue.push(options[i]);
+ notFoundValues.splice(notFoundValues.indexOf(selectedVal), 1);
+ break;
+ }
+ }
+ }.bind(this));
+ }
+ }
+ } else {
+ // single selection
+ if (selected && (typeof selected === 'string' || typeof selected === 'number')) {
+ var selectedVal = this._prepareValue(selected);
+ notFoundValues.push(selectedVal);
+ if (options instanceof Array && options.length > 0) {
+ for (i = 0; i < options.length; i++) {
+ if (this._prepareValue(options[i][this.optionValue]) === selectedVal) {
+ currentValue = options[i];
+ notFoundValues.splice(notFoundValues.indexOf(selectedVal), 1);
break;
}
}
- }.bind(this));
- }
- }
-
- } else {
- if ((selected && (typeof selected === 'string' || typeof selected === 'number')) &&
- options instanceof Array && options.length > 0) {
- var selectedVal = this._prepareValue(selected);
- notFoundValue.push(selectedVal);
- for (var i = 0; i < options.length; i++) {
- if (this._prepareValue(options[i][this.optionValue]) === selectedVal) {
- currentValue = options[i];
- notFoundValue.splice(notFoundValue.indexOf(selectedVal), 1);
- break;
}
}
}
- }
- if (JSON.stringify(this.value) !== JSON.stringify(currentValue)) {
- this.set('value', currentValue);
- }
+ this.set('notFoundValues', notFoundValues);
+ if (JSON.stringify(this.value) !== JSON.stringify(currentValue)) {
+ this.set('value', currentValue);
+ }
- // not found selected values in options
- if (notFoundValue.length > 0) {
- var warnMsg = '[etools-esmm] Selected ';
- if (notFoundValue.length === 1) {
- warnMsg += 'value ';
- } else {
- warnMsg += 'values '
+ // not found selected values in options
+ if (notFoundValues.length > 0) {
+ var warnMsg = '[etools-esmm] Selected ';
+ if (notFoundValues.length === 1) {
+ warnMsg += 'value ';
+ } else {
+ warnMsg += 'values '
+ }
+ warnMsg += notFoundValues.join(', ') + ' not found in dropdown\'s options!' ;
+ console.warn(warnMsg);
}
- warnMsg += notFoundValue.join(', ') + ' not found in dropdown\'s options!' ;
- console.warn(warnMsg);
- }
+ }.bind(this), 50);
},
_updateSelected: function(selectedValues, oldSelectedValues) {
@@ -771,6 +815,11 @@
return this._prepareValue(s);
}.bind(this));
}
+ if (this.notFoundValues.length) {
+ this.notFoundValues.forEach(function(notFoundVal) {
+ selectedVals.push(this._prepareValue(notFoundVal));
+ }.bind(this));
+ }
}
if (!this.multi) {
@@ -778,7 +827,12 @@
if (selectedValues && !(typeof selectedValues === 'string' && selectedValues === '')) {
selectedVals = this._prepareValue(selectedValues);
}
+ if (!selectedVals && this.notFoundValues.length) {
+ this.set('_prevSelectedValues', this.notFoundValues[0]);
+ return;
+ }
}
+
this.set('_prevSelectedValues', selectedVals);
this.set('selected', selectedVals);
}.bind(this), 50);