Unexpected behaviour with vue watcher (vue-2)

Hi,

Today I stumbled across a problem when using a watcher that I could solve, but I would like to understand the “story” behind it.

If you have a watcher to watch some form variables to set a dirty variable, like:

    data() {
      return {
        formWatcher: null,
        dirty: false,
        form: {
          id: '',
          content: '',
         updated_at: '' // will be the problem later
        }
      }
    },
...
      watchForm() {
        this.formWatcher = this.$watch('form', () => this.dirty = true, {deep: true})
      },
      unwatchForm() {
        this.setDirty(false)
        this.formWatcher()
      },
...
    async created() {
      ...
      this.watchForm()

    },

That’s nothing exceptional.

Basically, a variable is set to dirty to warn users before they leave that their changes won’t be saved.

Now my update method looked like:

      async update() {
          let response = await axios.put(`/foo/${this.id}`, this.form)
          let { updated_at } = response.data.data
          this.setFormAttribute('updated_at', updated_at)
          this.dirty = false // DOESN'T WORK
      },

When I tried to update an entry and then set dirty to false, I noticed that tough I explicitly set dirty to false, it is immediately set back to true.

That’s the line of code that is responsible for that:

     this.setFormAttribute('updated_at', updated_at)

That was very surprising as I expected that setting this form attribute would again trigger dirty = true, but as I attribute false to this.dirty just afterwards, I would have expected that this wouldn’t be the case.

So then, what worked was to separate the code as follows:

      async update() {
          let response = await axios.put(`/foo/${this.id}`, this.form)
          let { updated_at } = response.data.data
          this.setFormAttribute('updated_at', updated_at)
          return response // not really used but for the sake of it...
      },
...
      async submit() {
        await this.update()
        this.setDirty(false) // I live now here, which makes sure I am set to false after all variables are set
      },

So, I am happy with my code, everything works as expected, but can someone explain why the first approach didn’t work?

Were both variables set simultaneously? Or was “updated_at” set before dirty was set to false, as updated_at came from the database?

For instance, I noticed that for a very short moment dirty “danced” from false to true.

I hope that is not too weird, but would be great if someone has an idea (and can share some best practices)?