import BasicComponent from './basic-component'; import { observer } from '@ember/object'; import { A } from '@ember/array'; import $ from 'jquery'; export default BasicComponent.extend({ tagName: 'x-fake-el', options: [], 'value-field': 'value', 'text-field': 'text', 'enabled-field': null, 'hidden-input': true, loose: true, 'fire-init-change': true, 'values-as-string': true, 'values-splitter': ',', didReceiveAttrs() { const me = this; me._super(...arguments); // select first if (!me.get('multiple') && !me.get('nullable')) { const options = me.get('options'); if (options && options.length) { const val = me._getVal(); // no val or val not in options if (!val || !options.any(o => me.opEq(o, val))) { me._setVal(me.getOpVal(options[0])); } } } }, didInsertElement() { const me = this; me._super(...arguments); $(me.element).children('select.select2').select2({ multiple: me.get('multiple'), disabled: me.get('readonly'), allowClear: me.get('nullable'), placeholder: me.get('placeholder') || me.get('label') || 'Please select...', templateResult: me.get('tplResult'), templateSelection: me.get('tplSelection') }).on('change', function(e) { console.log('selection change: ', e); const selected = $(this).select2('data'); if (me.get('multiple')) { me._setVal(selected ? selected.map(o => o.id) : []); } else { const o = selected ? selected[0] : null; me._setVal(o ? o.id : null); } me.notifyChange(); }) // init val, trigger change required .val(me._getVal()).trigger('change'); if (me.get('fire-init-change')) { me.notifyChange(); } }, optionsChanged: observer('options', function() { const me = this; me.set('optionsUpdated', true); }), didUpdate() { const me = this; me._super(...arguments); if (me.get('optionsUpdated')) { me.set('optionsUpdated', false); const options = me.get('options'); const jqEl = $(me.element).children('select.select2'); if (me.get('multiple')) { me._setVal([]); // clear selection jqEl.val(null).trigger('change'); } else { const val = me._getVal(); // reset old val if (val && me.findOption(val)) { jqEl.val(val).trigger('change'); } else { const firstOption = options[0]; if (firstOption && !me.get('nullable')) { me._setVal(me.getOptVal(firstOption)); jqEl.val(val).trigger('change'); } else { me._setVal(null); jqEl.val(null).trigger('change'); } } } } }, findOption(val) { const me = this; return me.get('options').find(op => me.opEq(op, val)); }, notifyChange() { const me = this; const options = me.get('options'); const onChange = me.get('on-change'); onChange && onChange(me._getVal(), options); }, _getVal() { const me = this; const val = me.getVal(); if (me.get('multiple') && typeof val === 'string' && me.get('values-as-string')) { return A(val ? val.split(me.get('values-splitter')) : []); } return val; }, _setVal(val) { const me = this; me.setVal(me.get('multiple') && me.get('values-as-string') ? (val.length ? val.join(me.get('values-splitter')) : null) : val); }, isPlainVal(val) { return typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean' || ( (!!val && typeof val === 'object') && ['[object String]', '[object Number]', '[object Boolean]' ].includes(Object.prototype.toString.call(val)) ) }, getOpVal(op) { const me = this; return me.isPlainVal(op) ? op : op[me.get('value-field')]; }, opEq(op, val) { const me = this; let opv = me.getOpVal(op); return me.get('loose') ? opv == val : opv === val; } });