vue-meteor
vue-meteor copied to clipboard
3-way data binding / Full Stack Reactivity
I wondered if it's possible to implement full-stack reactivity in meteor-vue-component, similar to how angular-meteor does it: https://www.angular-meteor.com/tutorials/socially/angular2/3-way-data-binding
Basically, what it does is to call the corresponding Collection.update/insert/etc functions when the data model changes. For example, a text field with a v-model
would not only update the client-side data, but through reactivity, also update the collection in the database.
That should be possible!
Iv been trying to implement that but I'm n able to figure out I in th watcher which field h changed. So I'm now doing a collection.update(id, {$set: enitiredocument}
call. It would be nicer to make a call that sets only the changed fields.
You may look into flux integration into apollo which makes data sources management simpler, assuming that someday they'll integrate meteor into it, so that then youd need vuex/apollo for simple data management.
I heard that minimongo doesn't go deep looking into fields, so that would most likely be your own extend of reach, as well as that more so conscious of operating expense may be weary of such a direct binding in write/update to DB.
According to this: https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events
<input v-model="something">
is just syntactic sugar for:
<input v-bind:value="something" v-on:input="something = $event.target.value">
That being the case, wouldn't this be sufficient?
<style lang="stylus" src="./styles"></style>
<template>
<div id="app" class="app">
<template v-for="text in texts">
{{text.text}}
<br />
<input type="text" :value="text.text" @input="updateText" :data-id="text._id" />
<br />
</template>
</div>
</template>
<script>
import { Meteor } from 'meteor/meteor';
import Texts from '/imports/api/texts/texts';
export default {
name: 'App',
data: ()=> ({
texts: []
}),
meteor: {
subscribe: {
texts: []
},
texts() {
return Texts.find().fetch();
}
},
methods: {
updateText(e) {
Meteor.call('updateText', {
id: e.target.dataset.id,
text: e.target.value
});
}
}
};
</script>
In the above example, instead of updating the client text value directly, like what would happen with v-model
, we call the updateText method which updates the client text value through reactivity.
In any case, in order to get a method call in, you would have to specify which method to call using a v-on
, which makes using v-model
moot.
Or you could use computed setters with v-model
.
Well, shit. @Akryum When you're right, you're right.
How would you set that up for a field on each mongo document from a collection? Sub component, probably... Is there any way to do it without a sub component?
I've been using the collection-helpers
package to implement a save
method on documents (example: https://github.com/buhrmi/q-editor/blob/master/lib/collections.coffee#L149). Then I added a watcher like this:
watch: {
myDocument: {
deep: true,
sync: true,
handler: function(doc) {
if (!Tracker.active) doc.save();
}
}
}
The !Tracker.active
part is to ensure that the triggered watcher originated from Vue's reactivity and not from Meteor.
One thing I would like to see here is also latency compensation. So if a doc is changed using v-model
, a method runs on client and server to update the doc, then:
- doc should be updated from simulated value of the method
- if server-side updates doc differently, then client side doc should be updated to that value as well
Maybe this happens automatically because data flows from server and replaces those docs with new versions, but to me the issue with v-model
is that Vue renders UI based on locally changed doc, and not on doc changed by simulated method. But maybe simulated method can override locally changed doc if it conflicts. So we have two levels of correcting. Simulated method -> doc changed by Vue. And server side -> doc changed by simulated method.