0

I am not correctly understanding the usage pattern for using x-template for a subcomponent inside a vuejs component.

So, I have a component called CategoryNav.vue which has a template. Within that to display a list, we have used an x-template. But I render my page, it doesn't recognize this component created using the x-template. I think i am using it incorrectly. Any help is appreciated. Here is my main component code.

CategoryNav.vue

<template>
<div class="">
  <menu-list :items="treeList"></menu-list>
</div>
</template>

<script type="text/x-template" id="menu-list-template">
  <ul v-if="items.length">
    <li v-for="item of items">
      <a :href="item.value">{{ item.label }}{{ item.id }}</a>
      <menu-list :items="item.children"></menu-list>
    </li>
  </ul>
</script>
<script>
const MenuList = {
  name: 'menu-list',
  template: '#menu-list-template',
  props: ['items']
}

export default {
  name: 'category-nav',
  components: {
    MenuList
  },
  computed: {
    list () {
      return this.$store.state.topics
    },
    treeList () {
      const items = this.list.map(item => Object.assign({}, item, { children: [] }))
      const byValue = new Map(items.map(item => [item.value, item]))
      const topLevel = []
      for (const item of items) {
        const parent = byValue.get(item.parent)
        if (parent) {
          parent.children.push(item)
        } else {
          topLevel.push(item)
        }
      }
      return topLevel
    }
  }
}
</script>

2 Answers 2

3

This won't work. <script type="text/x-template" id="menu-list-template"> needs to exist in the DOM somewhere for Vue to find it, and since it is outside of the <template> section, vue-loader is going to treat it as a custom block (which will be ignored by default).

A single *.vue file is meant to contain one component only. I don't recommend mixing x-templates with vue-loader anyway. You should put every component into a *.vue file so that it gets precompiled, that way you don't need to bundle the vue compiler in your production build.

You can either:

  1. (Recommended) Extract the sub component into its own *.vue file and import it into the CategoryNav.vue module.
  2. You can define the sub component completely within CategoryNav.vue <script> section, but it cannot have a compiled template. You'll have to specify the render function for it (messy).
  3. Same as #2, except you can specify the template as a string, but you will need to ship the Vue compiler in your production build. If you want to use an x-template instead of a string, then you need to make sure that the x-template <script> is in the DOM.

See this for an explanation of the Vue build files.

Sign up to request clarification or add additional context in comments.

1 Comment

I used the first approach, that is, to extract the sub component in a separate file of its own and it is working correctly. Thank you once again!
0

You didn't declare component name 'menu-list', let's try this:

export default {
  name: 'category-nav',
  components: {
    'menu-list': MenuList
  },
....

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.