Zhengquan Bai
Zhengquan Bai

Reputation: 1073

Any easier way to access nested object properties in Vue template?

It's convenient to group data into nested object properties. By doing this, we don't have to collect properties from the data field into an entity for later use. As in the following example,

var demo = new Vue({
	el: '#demo',
        data: {
  	  level1: {
    	    level2: {
      	      level3_1: 'Hello',
              level3_2: 'world'
            }
          }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="demo">
  <div class="person">
    <h3>{{ level1.level2.level3_1 }}</h3>
    <p>{{ level1.level2.level3_2 }}</p>
  </div>
</div>

However, it's really overkill having to type the "level1.level2" prefix in order to get to the level3_x field. It'll be very cumbersome if there're loads of level3 fields.

I wonder if there is any way that I can save the work for typing level1.level2 over and over again. Does the template have any syntax so that some section is under the scope of "level1.level2"? Does Vue provide any support so that in this case the prefix "level1.level2" is assumed?

Upvotes: 3

Views: 13967

Answers (3)

reinerBa
reinerBa

Reputation: 1660

There are serval ways:

  1. Use a method that gets the same level

    methods:{ getLvl3: function(nr){ return this["level"+nr]["level"+nr]["level3_"+nr]; }

    {{ getLvl3(1) }}

  2. Iterate over with v-for v-for docu

example:

<div id="demo">
  <div class="person">
    <template v-for="(lvl2, key) in level1">
      <template v-for="(lvl3, key) in lvl2">
        <h3 v-if="key === 'level3_1'>{{ lvl3 }}</h3>
        <p v-if="key === 'level3_2'">{{ lvl3 }}</p>
      </template>
    </template>        
  </div>
</div>
  1. bind to variable that is defined outside of vue:

    var nested = { level1: { level2: { level3_1: 'Hello', level3_2: 'world' }}

and inside of vue component or instance:

data:{ 
  level2: nested.level1.level2,
}

<div id="demo">
  <div class="person">
    <h3>{{ level2.level3_1 }}</h3>
    <p>{{ level2.level3_2 }}</p>
  </div>
</div>

Upvotes: 0

feradz
feradz

Reputation: 1372

The example of @jason-smith is almost right. v-for is used for arrays or lists. To make it work is necessary to put your object in list.

Following his example the better approach would be

var demo = new Vue({
  el: '#demo',
  data: {
    level1: {
      level2: {
        level3_1: 'Level 3_1',
        level3_2: 'Level 3_2'
      }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <div class="person">
    <template v-for="level2Obj in [level1.level2]">
        <h3>{{ level2Obj.level3_1 }}</h3>
        <p>{{ level2Obj.level3_2 }}</p>
    </template>
  </div>
</div>

Upvotes: 0

Jason Smith
Jason Smith

Reputation: 1209

There are a couple of options.

1. Use v-for

Everything inside the v-for block is scoped to the level that you're iterating over. Do it like this:

var demo = new Vue({
	el: '#demo',
        data: {
  	  level1: {
    	    level2: {
      	      level3_1: 'Hello',
              level3_2: 'world'
            }
          }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="demo">
  <div class="person">
    <template v-for="(l2prop, l2propName) in level1">
        <h3>{{ l2prop.level3_1 }}</h3>
        <p>{{ l2prop.level3_2 }}</p>
    </template>
  </div>
</div>

2. Use a component

Components get a subset of their parent's data, so they're automatically scoped. Do it like this:

Vue.component( "person", {
    props: ['data'],
    template: '<div class="person"><h3>{{ data.level3_1 }}</h3><p>{{ data.level3_2 }}</p></div>'
});

var demo = new Vue({
	el: '#demo',
        data: {
  	  level1: {
    	    level2: {
      	      level3_1: 'Hello',
              level3_2: 'world'
            }
          }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="demo">
  <person v-bind:data="level1.level2"></person>
</div>

Upvotes: 6

Related Questions