Nested models and reactivity
riker09 opened this issue · comments
I'm not quite sure if this is an issue with vue-rawmodel or Vue.js. but it seems that the support for nested models is limited or broken. Please see this demo for reference: https://codepan.net/gist/a7fe8b888cf6b5e92c84350e9ed22fbc
Basically I have two reactive models, where one model is a child of the other.
class MyModel extends ReactiveModel {
name: string;
locked: boolean;
settings: Settings;
public constructor({parent, ...data} = {}) {
super({parent});
this.defineField('name', { type: 'String', defaultValue: '' });
this.defineField('locked', { type: 'Boolean', defaultValue: false });
this.defineField('settings', { type: Settings, defaultValue: function() { return new Settings(); } });
}
}
class Settings extends ReactiveModel {
dummy: boolean;
public constructor({parent, ...data} = {}) {
super({parent});
this.defineField('dummy', { type: 'Boolean', defaultValue: true });
}
}
I have a custom form component named form-toggle
looking like this:
Vue.component('form-toggle', {
props: {
value: { type: Boolean },
onValue: { type: Boolean, default: true },
offValue: { type: Boolean, default: false }
},
template: `<div>
<div class="toggle" :class="{on: isOn}">
<div class="val" :class="{active: !isOn}" @click="turnItOff">off</div>
<div class="val" :class="{active: isOn}" @click="turnItOn">on</div>
<div class="marker"></div>
</div>
</div>`,
computed: {
isOn: function() { return this.value === this.onValue }
},
methods: {
turnItOn: function() { this.$emit('input', this.onValue); },
turnItOff: function() { this.$emit('input', this.offValue); }
}
});
And now we put it all together:
new Vue({
el: "#app",
data: {
hasChanges: false,
myModel: new MyModel()
},
computed: {
status: function() { return this.hasChanges ? 'changed' : 'vanilla' }
},
methods: {
stateChanged: function() {
this.hasChanges = this.myModel.isChanged();
},
reset: function() {
this.myModel.$rollback();
this.hasChanges = this.myModel.isChanged();
}
}
});
</script>
For conveniance here's the template:
<div id="app">
<h2>Model status: {{ status }}</h2>
<div>
<label for="name">
Name:
<input id="name" v-model="myModel.Name" @input="stateChanged" />
</label>
</div>
<div>
<p>Locked: {{myModel.locked}}</p>
<form-toggle v-model="myModel.locked" @input="stateChanged"></form-toggle>
</div>
<div>
<p>settings.dummy: {{myModel.settings.dummy}}</p>
<form-toggle v-model="myModel.settings.dummy" @input="stateChanged"></form-toggle>
</div>
<button @click="reset">Reset</button>
<h2>
Raw output:
</h2>
{{ myModel }}
</div>
When I change the value of a non-nested property I'm unable to change the value of a nested property until I either reset ($rollback
) the model or change the values back to their original state.
It feels like I'm missing something very obvious, but I've been trying to figure this one out for quite some time now. Hopefully you can shine some light on this?