1

Say we have two routes: edit/1 and edit/new

The root container (on mount) checks if there is a this.$route.params.id and if so, fetches the data from the API and fills the obj. Otherwise, the obj in question remains empty.

This object is sent to a child component which has something like:

<template>
  <input v-model="obj.name">
  <input v-model=obj.email">
</template>

<script>
export default {
  props: {
    obj {
      type: Object,
      default: () => {}
    }
  },
}
</script>

The issue I'm having right now is that when I send an empty object nothing renders. Would this issue have anything to do with the empty object? As far as I can tell, properties can be added dynamically like this in Vue.

Should you need more information, please ask!

Riza Khan
  • 2,712
  • 4
  • 18
  • 42

2 Answers2

2

Just for the record

default: () => {}

Will not return an empty object as a default. The arrow function will return void. If you're trying to set an empty object as a default use

default: () => ({})

Anyway as prop mutations are not only discouraged, they're considered an anti-pattern in Vue2 (see Vue 2 - Mutating props vue-warn) you should add a data field that either already declares default values or get's its default from the corresponding prop field

props: {
  obj: {
    type: Object,
    default: () => ({ name: '', email: '' })
  }
}
data() {
  return {
    name: this.obj.name,
    email: this.obj.email,
  }
}
Braks
  • 561
  • 2
  • 9
1

The problem is you need to either declare the prop members in the object, or use Vue.set to add new reactive properties from the parent.

default: () => ({name:null, email:null})
// or
default: () => { return {name:null, email:null} }

or in the parent

Vue.set(defaultObjWithoutMembers, 'name', 'foo')

Vue2 is not able to detect or track properties that are not part of the original object declaration.

See https://v2.vuejs.org/v2/guide/reactivity.html

tony19
  • 125,647
  • 18
  • 229
  • 307
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
  • 1
    but `v-model` mutates the prop which is not allowed in vue – Boussadjra Brahim Jul 16 '21 at 15:57
  • its allowed, but discouraged. and even so, using :value and @input('$emit'...) to change won't detect new properties. – Steven Spungin Jul 16 '21 at 15:58
  • 1
    I'm using `:obj.sync="obj"` and it works fine if the obj is full – Riza Khan Jul 16 '21 at 16:02
  • @StevenSpungin Ok your Vue.set method worked! But, I wanted to add that not all properties required it. Only arrays (in my case). Could you explain why? – Riza Khan Jul 16 '21 at 17:23
  • The javascript runtime that Vue2 runs in uses a proxy that can only track what it sees when it initially scans the object. So using `Vue.set` is the work around, or declaring null or undefined props. Also note i put your default function in `( )` now to return an object, as stated in Braks post. Vue3 does not have this issue BTW. – Steven Spungin Jul 16 '21 at 19:08
  • Keep in mind, certain array functions will also not be reactive unless using Vue.set on the array elements. This is all documented on Vue's website. I will put a link in the solution. – Steven Spungin Jul 16 '21 at 19:10