Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a proper way of resetting a component's initial data in vuejs?

I have a component with a specific set of starting data:

data: function (){
    return {
        modalBodyDisplay: 'getUserInput', // possible values: 'getUserInput', 'confirmGeocodedValue'
        submitButtonText: 'Lookup', // possible values 'Lookup', 'Yes'
        addressToConfirm: null,
        bestViewedByTheseBounds: null,
        location:{
            name: null,
            address: null,
            position: null
        }
}

This is data for a modal window, so when it shows I want it to start with this data. If the user cancels from the window I want to reset all of the data to this.

I know I can create a method to reset the data and just manually set all of the data properties back to their original:

reset: function (){
    this.modalBodyDisplay = 'getUserInput';
    this.submitButtonText = 'Lookup';
    this.addressToConfirm = null;
    this.bestViewedByTheseBounds = null;
    this.location = {
        name: null,
        address: null,
        position: null
    };
}

But this seems really sloppy. It means that if I ever make a change to the component's data properties I'll need to make sure I remember to update the reset method's structure. That's not absolutely horrible since it's a small modular component, but it makes the optimization portion of my brain scream.

The solution that I thought would work would be to grab the initial data properties in a ready method and then use that saved data to reset the components:

data: function (){
    return {
        modalBodyDisplay: 'getUserInput', 
        submitButtonText: 'Lookup', 
        addressToConfirm: null,
        bestViewedByTheseBounds: null,
        location:{
            name: null,
            address: null,
            position: null
        },
        // new property for holding the initial component configuration
        initialDataConfiguration: null
    }
},
ready: function (){
    // grabbing this here so that we can reset the data when we close the window.
    this.initialDataConfiguration = this.$data;
},
methods:{
    resetWindow: function (){
        // set the data for the component back to the original configuration
        this.$data = this.initialDataConfiguration;
    }
}

But the initialDataConfiguration object is changing along with the data (which makes sense because in the read method our initialDataConfiguration is getting the scope of the data function.

Is there a way of grabbing the initial configuration data without inheriting the scope?

Am I overthinking this and there's a better/easier way of doing this?

Is hardcoding the initial data the only option?

like image 898
Chris Schmitz Avatar asked Feb 24 '16 14:02

Chris Schmitz


People also ask

How do I reset Vue project?

To reset a component's initial data in Vue. js, we can create a function that returns the initial data. Then we can call the function to reset the data. to create the initialState function that returns an object with the initial data.

How do you clear an object in Vue?

To delete a property from a data object with Vue. js, we can use the this. $delete method. to delete the foo property from the this.

How do you clear the input field after submitting Vue?

In vue. js, we use the v-model directive to create a two-way data binding between the input field and vue data property, so that we can clear an input field value by setting the empty string (" ") to the data property.


6 Answers

  1. extract the initial data into a function outside of the component
  2. use that function to set the initial data in the component
  3. re-use that function to reset the state when needed.

// outside of the component:
function initialState (){
  return {
    modalBodyDisplay: 'getUserInput', 
    submitButtonText: 'Lookup', 
    addressToConfirm: null,
    bestViewedByTheseBounds: null,
    location:{
      name: null,
      address: null,
      position: null
    }
  }
}

//inside of the component:
data: function (){
    return initialState();
} 


methods:{
    resetWindow: function (){
        Object.assign(this.$data, initialState());
    }
}
like image 65
Linus Borg Avatar answered Oct 05 '22 10:10

Linus Borg


Caution, Object.assign(this.$data, this.$options.data()) does not bind the context into data().

So use this:

Object.assign(this.$data, this.$options.data.apply(this))

cc this answer was originally here

like image 37
Roland Avatar answered Oct 05 '22 08:10

Roland


To reset component data in a current component instance you can try this:

Object.assign(this.$data, this.$options.data())

Privately I have abstract modal component which utilizes slots to fill various parts of the dialog. When customized modal wraps that abstract modal the data referred in slots belongs to parent component scope. Here is option of the abstract modal which resets data every time the customized modal is shown (ES2015 code):

watch: {
    show (value) { // this is prop's watch
      if(value) {
        Object.assign(this.$parent.$data, this.$parent.$options.data())
      }
    }
}

You can fine tune your modal implementation of course - above may be also executed in some cancel hook.

Bear in mind that mutation of $parent options from child is not recommended, however I think it may be justified if parent component is just customizing the abstract modal and nothing more.

like image 39
gertas Avatar answered Oct 05 '22 09:10

gertas


If you are annoyed by the warnings, this is a different method:

const initialData = () => ({})

export default {
  data() {
    return initialData();
  },
  methods: {
    resetData(){
      const data = initialData()
      Object.keys(data).forEach(k => this[k] = data[k])
    }
  }
}

No need to mess with $data.

like image 38
srmico Avatar answered Oct 05 '22 09:10

srmico


I had to reset the data to original state inside of a child component, this is what worked for me:

Parent component, calling child component's method:

<button @click="$refs.childComponent.clearAllData()">Clear All</button >
       
<child-component ref='childComponent></child-component>

Child component:

  1. defining data in an outside function,
  2. referencing data object by the defined function
  3. defining the clearallData() method that is to be called upon by the parent component
function initialState() {
  return { 
    someDataParameters : '',
    someMoreDataParameters: ''
  }
}

export default {
   data() {
    return initialState();
  },
methods: {
  clearAllData() {
    Object.assign(this.$data, initialState());
},
like image 27
Armin Avatar answered Oct 05 '22 09:10

Armin


There are three ways to reset component state:

  1. Define key attribute and change that
  2. Define v-if attribute and switch it to false to unmount the component from DOM and then after nextTick switch it back to true
  3. Reference internal method of component that will do the reset

Personally, I think the first option is the clearest one because you control the component only via Props in a declarative way. You can use destroyed hook to detect when the component got unmount and clear anything you need to.

The only advance of third approach is, you can do a partial state reset, where your method only resets some parts of the state but preserves others.

Here is an example with all the options and how to use them: https://jsbin.com/yutejoreki/edit?html,js,output

like image 32
Buksy Avatar answered Oct 05 '22 09:10

Buksy