Categories
Vue

How to Properly Watch for Nested Data with Vue.js

Spread the love

Watching for deeply nested object states and props is something that we often have to do in a Vue.js app.

In this article, we’ll look at how to properly watch for nested data in Vue.js components.

Deep Watchers

We can add deep watchers to components within the watch property.

For instance, we can write:

App.vue

<template>
  <div id="app">
    <button
      @click="
        id++;
        getTodo(id);
      "
    >
      increment id
    </button>
    <Todo :todo="todo" />
  </div>
</template>

<script>
import Todo from "./components/Todo";

export default {
  name: "App",
  components: {
    Todo,
  },
  data() {
    return {
      todo: {},
      id: 1,
    };
  },
  methods: {
    async getTodo(id) {
      const results = await fetch(
        `https://jsonplaceholder.typicode.com/todos/${id}`
      );
      const data = await results.json();
      this.todo = data;
    },
  },
};
</script>

Todo.vue

<template>
  <div class="hello"></div>
</template>

<script>
export default {
  name: "Todo",
  props: {
    todo: Object,
  },
  watch: {
    todo: {
      handler(val) {
        console.log(val);
      },
      deep: true,
    },
  },
};
</script>

We have a button that calls getTodo when we get it to get a new todo object with the given id .

getTodo updates the todo reactive property from the response.

We pass the todo value to the todo prop of the Todo component.

Then in the Todo component, we watch the todo prop with the watch property.

We have the handler function with the val parameter to get the latest value.

deep is set to true so that we can watch for properties object props.

Computed Property

We can create a computed property to get the property from a reactive property.

For instance, we can write:

Todo.vue

<template>
  <div>{{ todoTitle }}</div>
</template>

<script>
export default {
  name: "Todo",
  props: {
    todo: Object,
  },
  computed: {
    todoTitle() {
      return this.todo.title;
    },
  },
};
</script>

We keep App.vue the same.

We created the todoTitle computed property that returns the this.todo.title property.

Then we can use it in the template like any other reactive property.

todoTitle will be updated whenever any property in the this.todo object is updated.

Watch a Property of an Object

We can also watch a property of an object.

For instance, we can write:

<template>
  <div class="hello"></div>
</template>

<script>
export default {
  name: "Todo",
  props: {
    todo: Object,
  },
  watch: {
    "todo.title": {
      handler(val) {
        console.log(val);
      },
    },
  },
};
</script>

Then the title property from the todo prop is watched with the watcher.

This is because 'todo.title' is the title property of the todo prop.

val would have the value of the title property of the todo prop.

We can get the newVal and oldVal from the watcher function:

<template>
  <div class="hello"></div>
</template>

<script>
export default {
  name: "Todo",
  props: {
    todo: Object,
  },
  watch: {
    "todo.title": {
      handler(newVal, oldVal) {
        console.log(newVal, oldVal);
      },
    },
  },
};
</script>

Conclusion

We can watch for nested properties with watchers by adding methods to the watch property object with a property path.

Also, we can set deep to true to watch for deeply nested properties.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *