Created
June 19, 2015 04:13
-
-
Save eccegordo/e7c9e8ac03cbbaf3c19b to your computer and use it in GitHub Desktop.
custom select component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
export default Ember.Component.extend({ | |
options: null, | |
value: null, | |
prompt: null, | |
valuePath: null, | |
labelPath: null, | |
tagName: 'select', | |
handleChange: null, | |
// selection: null, | |
selectedOption: null, | |
updateSelectedOptionObserver: Ember.observer('value', 'options.@each', function(){ | |
this.updateSelectedOption(); | |
this.triggerChangeAction(); | |
}), | |
updateSelectedOption: function(){ | |
var self = this; | |
var value = this.get('value'); | |
var options = this.get('options'); | |
if (Ember.isBlank(options)){ | |
this.set('selectedOption', null); | |
return; | |
} | |
// Convert to an ember array if not already | |
if (options.objectAt === undefined){ | |
options = Ember.A(options); | |
} | |
// Find the option that matches the value. | |
for (let i = 0; i < options.get('length'); i++) { | |
var option = options.objectAt(i); | |
if (self.valueOfOption(option) == value){ // jshint ignore:line | |
this.set('selectedOption', option); | |
return; | |
} | |
}// end for | |
// If the option was not found | |
this.set('selectedOption', null); | |
}, | |
triggerChangeAction: function () { | |
var handleChange = this.get('handleChange'); | |
var value = this.get('value'); | |
var selectedOption = this.get('selectedOption'); | |
if (!Ember.isBlank(handleChange)){ | |
this.sendAction('handleChange', value, selectedOption); | |
} | |
}, | |
didRender: function(){ | |
var self = this; | |
this.$().on('change', function(event){ | |
var selected = Ember.$(event.target).find('option:selected'); | |
var selectedOption = selected.data('optionObject'); | |
self.set('value', self.valueOfOption(selectedOption)); | |
}); | |
this.updateOptions(); | |
this.updateSelectedOption(); | |
}, | |
// Use the value path to get the value for the option passed in. | |
// if no value path, return the option as the value so the dropdown | |
// works with POJOs and arrays. | |
valueOfOption: function (option) { | |
if (Ember.isBlank(option)){return null;} | |
var defaultValuePath = 'value'; | |
var valuePath = this.get('valuePath'); | |
var valuePathIsSet = !Ember.isBlank(valuePath); | |
if (valuePathIsSet && option.get){ | |
return option.get(valuePath); | |
} else if (!valuePathIsSet && !Ember.isBlank(option.get) && option.get(defaultValuePath) !== undefined){ | |
return option.get(defaultValuePath); | |
} else if (!valuePathIsSet && option[defaultValuePath] !== undefined){ | |
return option[defaultValuePath];// must be pojo | |
} else if (valuePathIsSet && option[valuePath] !== undefined){ | |
return option[valuePath];// must be pojo | |
} else if (option && option.constructor.toString() === 'DS.PromiseObject'){ | |
return option.get('content'); | |
} else { | |
return option; | |
} | |
}, | |
// Use the value path to get the value for the option passed in. | |
// if no value path, return the option as the value so the dropdown | |
// works with POJOs and arrays. | |
labelForOption: function (option) { | |
if (Ember.isBlank(option)){return '';} | |
var defaultLabelPath = 'label'; | |
var labelPath = this.get('labelPath'); | |
var labelPathIsSet = !Ember.isBlank(labelPath); | |
var label; | |
if (labelPathIsSet && option.get) { | |
label = option.get(labelPath); | |
} else if (!labelPathIsSet && option.get && option.get(defaultLabelPath) !== undefined) { | |
label = option.get(defaultLabelPath); | |
}else if (!labelPathIsSet && option[defaultLabelPath] !== undefined) { | |
label = option[defaultLabelPath]; | |
}else if (labelPathIsSet && option[labelPath] !== undefined) { | |
label = option[labelPath]; | |
}else if (option.label !== undefined) { | |
label = option.label; | |
} else { | |
label = option; | |
} | |
return label; | |
}, | |
showPrompt: Ember.computed('prompt', function(){ | |
return true; //this.get('prompt') !== null; | |
}), | |
optionsObserver: Ember.observer('options', 'options.isPending', 'options.@each', 'value', function(){ | |
this.updateOptions(); | |
}), | |
updateOptions: function(){ | |
var self = this; | |
var options = this.get('options'); | |
var prompt = this.get('prompt'); | |
var value = this.get('value'); | |
var hasPrompt = !Ember.isBlank(prompt); | |
var optionTag; | |
var optionValues; | |
var didSetSelected = false; | |
if (this.$() === undefined){return;}// skip if not render yet | |
if (Ember.isEmpty(options)){return;} // skip if no options | |
if (options.get && options.get('isPending') === true){return;} | |
// Conver to an ember array if not already | |
if (options.objectAt === undefined){ | |
options = Ember.A(options); | |
} | |
// DS.PromiseObject is a special case where content null until it resolves | |
if (value && value.constructor.toString() === 'DS.PromiseObject') { | |
value = value.get('content'); | |
} | |
optionValues = options.map(function(o){return self.valueOfOption(o);}); | |
// clear out all options so we don't keep adding new | |
// ones if the array chagnes. | |
this.$().find('option').remove(); | |
// Add the prompt if user specified or the selection value is blank. | |
if(hasPrompt){ | |
optionTag = Ember.$(document.createElement('option')); | |
optionTag.text(prompt); | |
self.$().append(optionTag); | |
} | |
// Create option tags and set selected=true for the selected one | |
options.forEach(function(option){ | |
var innerText = self.labelForOption(option); | |
optionTag = Ember.$(document.createElement('option')); | |
optionTag.text(innerText); | |
optionTag.data('optionObject', option); | |
if (self.valueOfOption(option) == value){// jshint ignore:line | |
didSetSelected = true; | |
optionTag.prop('selected', true); | |
} | |
self.$().append(optionTag); | |
}); | |
// If the selection is not in the list of options (ie, the options changed or the value is no longer available) | |
// set the selected to the first item or nil if there is a prompt. | |
if (didSetSelected === false && optionValues.indexOf(value) === -1){ | |
if (hasPrompt) { | |
if (value !== null){ | |
this.set('value', null); | |
} | |
} else if (optionValues.length > 0) { | |
this.set('value', optionValues[0] ); | |
} | |
} | |
// // If no options became selected via prior loop | |
// // and no prompt then select the first option. | |
if (!hasPrompt && (value === null || value === undefined) && options.get('length') > 0){ | |
this.set('value', optionValues[0] ); | |
} | |
},//.on('didRender') | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment