Do you find yourself wanting to extend a component’s template? Vue provides several means of extracting and reusing the component logic and state, but templates are deemed single-use only.

In this article, I’ll present a solution using the HTML template pre-processor Pug. It’s a bit of a hack, but it does work!

If you’re looking to extend a component’s logic and state, you probably want to read my other article Extending Vue.js Components which covers composition functions, mixins, higher-order components, etc. Here we’re talking about the template.


Case study: a survey app

Let’s say you’re trying to make a component-based survey app with Vue which looks like this:

Notice that each survey question has a different input type:

  1. Text input
  2. Select input
  3. Radio input

An obvious architecture would be to make each question into a separate component, which is what we’re going to do. Well name these components:

  1. SurveyInputText
  2. SurveyInputSelect
  3. SurveyInputRadio

Base component

Let’s first create a “base” component called SurveyInput.vue. Notice the following about it:

  • The question prop is going to be common across each component. This captures the question text e.g. “What is your name”.
  • We don’t have any shared logic, but you could add it e.g. validation and error logic
  • I’m leaving a gap where the input element will need to go. This is where we’ll extend the template as you’ll shortly see.
<template>
  <div class="wrapper">
    <h4>{{ question }}</h4>
    <!--the appropriate input element should go here-->
  </div>
</template>
<script>
export default {
  props: {
    question: String  
  }
}
</script>

State and logic reuse

Ignoring the template for a moment, what will be our strategy for extraction and reuse of the state/logic? What we choose here will not affect our ability to extend the component template, so feel free to use mixins, higher-order components, or even the new composition API. I’m going to keep it simple and use the extends component option.

Again, there’s still a hanging question about how we get the base template into this subcomponent, as the Vue.extends API doesn’t apply to templates!

<template>
  <!--The base template needs to be here-->
  <input :placeholder="placeholder">
</template>
<script>
import SurveyInput from './SurveyInput.vue';
export default {
  extends: SurveyInput,
  props: {
    placeholder: String
  }
}
</script>

#vue.js #components #composition api #templates #vue

Extending Vue Component Templates
44.20 GEEK