Victor
Victor

Reputation: 5363

Skip watcher in vueJS

I have a form for updating document entity.

The document entity consists of list of employees (which is an array of objects) and each employee has a post which is just a string.

I have a dropdown (kind of wrapper for vue-multiselect) which accepts the array of employees and syncs selected employee to a selectedEmployee variable in data().

And also I have a watcher for selectedEmployee which sets the post input automatically when an employee is selected in the dropdown.

So, when creating a document in the form everything's fine, however, when I update the document, then I fetch existing document from server, set selectedEmployee and set employee's post. But, the document also keeps employee's post, so the first time when I open document's form in order to update it, I don't want to automatically update document's post. I want it to be updated only when user actually selects employee himself.

But the watcher gets called the first time too.

So, imagine we have John Doe and his a manager. When I create the document, I change his post to designer. Then, I open up the document form in order to update it, and I should see that for this specific document John Doe's post is "designer", but the watcher gets called and returns the post to manager.

I tried to make a fake variable in data(), like doneFetching, but it works only if I update this var directly in watcher, which looks quite dangerous, plus, in other entities I have many different kinds of selected employees, so making tons of fake flags is not an option.

Here is real code sample (employee = representative in my case):

  selectedApproveRepresentative(representative) {
    if (!representative) {
      this.memoData.approve_representative_id = null
      return
    }

    this.memoData.approve_representative_id = representative.id

    // Here is temporary solution, but I have many watchers for many different kinds of employees. If I move the doneFetching flag after I initialized the form, it'll be set to true, and only after that the watcher will be called
    if (this.mode === 'update' && !this.doneFetching) {
      this.doneFetching = true
      return
    }

    // In normal case a representative might have or have not post, so depending on this case we set it to be empty or filled. But this should not be called the first time I open the form
    this.memoData.approve_representative_post_dative_case =
      representative.post_dative_case ?
      representative.post_dative_case : ''
  },

Here is where I initialize data:

created() {
  if (this.memo) {
    this.memoData = _.cloneDeep(this.memo)
    this.selectedApproveRepresentative   = _.cloneDeep(this.memo.approve_representative)

  }
},

Upvotes: 1

Views: 1052

Answers (1)

DobleL
DobleL

Reputation: 3928

as I understood, your problem is the watcher executed when you init the component. Have you tried setting the immediate property of the watcher to false?

Not everybody knows that the watchers can be defined in different ways.

The simple one that everybody know

watchers: {
   propertyToWatch() { //code... }
}

Passing the name of a function as 'string'

watchers: {
   propertyToWatch: 'nameOfAfunctionDefinedInMethodsSection'
}

The object declaration

This one is the most descriptive way of declaring a watcher. You write it as an object with a handler property (it can be the name of a function passed as string as above), and other properties like deep to watch nested properties of an object, or in your case immediate which tells to the watcher if the should run immediately when the component is mounted.

watchers: {
   propertyToWatch: {
      immediate: false,
      handler: function() { //code.. }
   }
}

Upvotes: 1

Related Questions