Skip to content

Instantly share code, notes, and snippets.

@paltman
Created July 17, 2018 13:58
Show Gist options
  • Save paltman/fd016afe235161cb384cb4b1419a673b to your computer and use it in GitHub Desktop.
Save paltman/fd016afe235161cb384cb4b1419a673b to your computer and use it in GitHub Desktop.

I have settled into using this pattern to build Vue components that are editing content that is loaded into my Vuex store.

It feels like a lot of boilerplate to me so I'm not sure if I'm doing something wrong or un-Vue-like.

I load a copy of what's in the local store to local state so that the edits occur locally instead of modifying my state so that my state always represents what's in my database. This allows me to do things like compute dirty states for local components. It always just feels like the right thing to do.

My store's state only updates when data is returned from API calls to my backend database.

You can see here that in my components for each field I:

  1. create a field in my data()'s model. I nest inside model to avoid name conflict with my mapState properties. It also nicely segments model data from other UI state data I might need or want.
  2. add a load* method to copy in data to the local model from the mapState property
  3. call each load* method in both a watch method for that property as well as the mounted() lifecycle hook.

In this example, it's not too bad but when I have a component that is editing 6 fields or so, it's a LOT of boilerplate that seems very repetitive.

<template>
<div class="setup-form">
<my-editor v-model.trim="model.content" output="html"></my-editor>
<submit-button @click="save">Save</submit-button>
</div>
</template>
<script>
import { mapState } from 'vuex';
import MyEditor from '../../../components/MyEditor.vue';
import SubmitButton from '../../../components/SubmitButton.vue';
export default {
name: 'setup-form',
data () {
return {
model: {
content: ''
}
}
},
methods: {
save (done) {
this.$store.dispatch('saveContent', {
content: this.model.content
}).then(() => {
done();
});
},
loadContent() {
this.model = {...this.model, content: this.content}
}
},
computed: {
...mapState(['content'])
},
watch: {
content() {
this.loadContent()
}
},
mounted() {
this.loadContent()
},
components: {
MyEditor,
SubmitButton
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment