5

so I have a component that is rendering a form and it also is pre-filling the fields with data received from ajax request.

My issue is that I want to not only be able to edit fields but also add new fields to submit at the same time, so because of this I am trying to initialize my pre-filled data and new data into the same Object to be submitted with my ajax request. With my current set up the form-data is not consistently filling in the fields before the form is rendered.

This is the form template

<form @submit.prevent="editThisWorkflow" class="d-flex-column justify-content-center" >

 <div>
   <input type="text" v-model="workflowData.workflow">
    </div>
    <div >
    <div v-for="object in workflowData.statuses" :key="object.id">
    <input type="text" v-model="object.status">
    </div>
    <div v-for="(status, index) in workflowData.newStatuses" :key="index">
    <input type="text" placeholder="Add Status" v-model="status.value">
    <button type="button" @click="deleteField(index)">X</button>
    </div>
    <button type="button" @click="addField">
      New Status Field
    </button>
    </div>
    <div>
    <div>
    <button type="submit">Save</button>
    <router-link  :to="{ path: '/administrator/workflows'}" >Cancel</router-link>
  </div>
 </div>

</form>

This is the script

data() {
        return {
            workflowData: {
                id: this.$store.state.workflow.id,
                workflow: this.$store.state.workflow.workflow,
                statuses: this.$store.state.workflow.statuses,
                newStatuses: []
            },
            workflowLoaded: false
        }
    },
    computed: {
    ...mapGetters(['workflow']),
  },
  methods: {
    ...mapActions(['editWorkflow']),
    editThisWorkflow() {
        this.editWorkflow({
           id: this.workflowData.id,
           workflow: this.workflowData.workflow,
           statuses: this.workflowData.statuses,
           newStatuses: this.workflowData.newStatuses
        })
    },
    addField() {
        this.workflowData.newStatuses.push({ value: ''});
    },
    deleteField(index) {
        this.workflowData.newStatuses.splice(index, 1);
    }

And this is the store method to submit the data

editWorkflow(context, workflowData) {
      axios.patch('/workflowstatuses/' + workflowData.id, {
        workflow: workflowData.workflow,
        statuses: workflowData.statuses,
        newStatuses: workflowData.newStatuses
      })
      .then(response => {
          context.commit('editWorkflow', response.data)
      })
      .catch(error => {
          console.log(error.response.data)
      })           
    },

My problem comes in here

 data() {
        return {
            workflowData: {
                id: this.$store.state.workflow.id,
                workflow: this.$store.state.workflow.workflow,
                statuses: this.$store.state.workflow.statuses,
                newStatuses: []
            },
            workflowLoaded: false
        }
    },

Is there a better way to set this part??

workflowData: {
    id: this.$store.state.workflow.id,
    workflow: this.$store.state.workflow.workflow,
    statuses: this.$store.state.workflow.statuses,
    newStatuses: []
},

3 Answers 3

0

If you only need to assign store values to your form once then you can use mounted function.

mounted: function() {
   this.id = this.$store.state.workflow.id
   this.workflow = this.$store.state.workflow.workflow
   this.statuses = this.$store.state.workflow.statuses
},
data() {
      return {
          workflowData: {
              id: '',
              workflow: '',
              statuses: '',
              newStatuses: []
          },
          workflowLoaded: false
      }
 },
Sign up to request clarification or add additional context in comments.

1 Comment

so the data gets mounted correctly, however it is not consistent. Hopefully I can explain this correctly but when I cancel the form, and select a different workflow to edit, it populates the form with the previous workflow data. However if I cancel again and reselect the same workflow it will populate the form correctly...
0

the data property does not accept this, I usually use arrow function in this question because it prohibits me from using this, and prohibits my team from also using this within the data. Declare all necessary items within the datato maintain reactivity, and assign the value within the mounted of the page.

mounted() {
   this.workflowData.id = this.$store.state.workflow.id
   this.workflowData.workflow = this.$store.state.workflow.workflow
   this.workflowData.statuses = this.$store.state.workflow.statuses
},

data: () => ({
   workflowData: {
                id: '',
                workflow: '',
                statuses: '',
                newStatuses: []
            },
            workflowLoaded: false
        }
    },
})

1 Comment

so the data gets mounted correctly, however it is not consistent. Hopefully I can explain this correctly but when I cancel the form, and select a different workflow to edit, it populates the form with the previous workflow data. However if I cancel again and reselect the same workflow it will populate the form correctly...
0

The way how I resolved this problem turned out to be simpler than most of the solutions presented here. I found it hard to reach data from this.$store.state due to Vuejs life cycle. And assigning values to v-mode tourned out to be impossible because "v-model will ignore the initial value, checked or selected attributes found on any form elements. It will always treat the Vue instance data as the source of truth."

Solution

To pre-fill the field with data received from ajax request e.g. input field of type email I did as follow.

1st. I saved the output of my ajax request in application's storage (Cookies) -it can be Local Storage or Session, depended what is appropriate to you.

2nd. I populated my Vuex's store (single source of truth) with the data from my application storage. I do it every time when I reload a page.

3rd. Instead of binding a data to v-model in Vuejs life cycle, or using value attribute of html input (<input type="email" value="[email protected]">). I Pre-filled input by populating placeholder attribute of html with data coming from Vuex store like this:

<input v-model="form.input.email" type="email" name="email" v-bind:placeholder="store.state.user.data.email">

1 Comment

how can you call this approach simple?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.