vue-material
vue-material copied to clipboard
[MdSelect] Can't assign an object to md-option value
Currently, md-option
value doesn't accept Objects, which I think is an arbitrary limitation in a web-app.
<md-field>
<md-select v-model="selectedItem">
<md-option v-for="item in items" :value="item"> {{ item.name }} </md-option>
</md-select>
</md-field>
The thing is that, besides throwing a warning because the type Object
is not working, this paradigm already works. It doesn't however get shown correctly in the input field because it gets the content from the value instead that from the text content of the node, which is counter-intuitive.
We know about this, for now you can get your object like this:
Make your select options value as id
This functions are computed For select
getObject () {
return this.myArrayOfObjects.find((item) => (item.id === this.selectedItem))
},
For multi select
getObjects () {
return this.myArrayOfObjects.filter((item) => this.selectedItems.includes(item.id))
},
Live example: https://codesandbox.io/s/ww8yzzro3l
Yes, thank you: that's the workaround I used, actually setting up the data in those computed properties (the model I am trying to access is deeply nested in the object). It's pretty ugly though, but I am glad you guys are aware of it.
The select component is a drag, but it could use many improvements.
How would I apply this fix to the following?
'<md-field>'+
' <label>{{data.display}}</label>' +
'<md-select v-model="formInput" md-dense :disabled="enableEdit">' +
'<md-option :key="option" v-for="(option,index) in choiceCompute" :value="{ID: option.ID, Title: option[data.lookup.field]}">{{option[data.lookup.field]}}</md-option>' +
'</md-select>' +
' </md-field>' +
This works using standard html selects, using md-select when I click an option the data selected is correct but the display text is wrong.
@tachiaus yes because value cant be object, use my computed methods to get your selected object
@tachiaus @sunyatasattva i forget to mention i edited my last comment and added live example how to use that computed methods
@Samuell1 any news on this issue?
@Samuell1 your work around expects, that you can enumerate all the select boxes you are using. So using select boxes in a loop would no longer be possible.
Couldnt one use the following option:
<md-select v-model="getSystemConfigSetter(hc).key" name="systemConfigs" required>
<md-option v-for="option in options" :value="option.key">{{option.name}}</md-option>
</md-select>
@Component
class XYZ extends Vue {
public options: Option[];
public selectedOption: Option;
public getSystemConfigSetter(hostConfig: HostConfig): SetterByKey<SystemConfig> {
return new SetterByKey<SystemConfig>(
() => this.selectedOption,
(option: Option) => { this.selectedOption = option; },
this.options,
(option: Option) => option.key);
}
}
class Option {
key: string;
name: string;
}
// Util once per Project
function ensure<T>(argument: T | undefined | null, message: string = 'This value was promised to be there.'): T {
if (argument === undefined || argument === null) {
throw new TypeError(message);
}
return argument;
}
class SetterByKey<T> {
private readonly getValue: () => T;
private readonly setValue: (newValue: T) => void;
private readonly options: T[];
private readonly getKey: (optionType: T) => string;
public constructor(
getValue: () => T,
setValue: (newValue: T) => void,
options: T[],
getKey: (optionType: T) => string) {
this.getValue = getValue;
this.setValue = setValue;
this.options = options;
this.getKey = getKey;
}
get key(): string {
return this.getKey(this.getValue());
}
set key(key: string) {
this.setValue(ensure(this.options.find(option => this.getKey(option) === key)));
}
}