0

I want to use a component template depending on the client I have (the client ID is set in the env file)... so what I would like is something like this

<template :src="'../themes/' + process.env.VUE_APP_CLIENT + '/assets/views/myComponent.vue'"></template>

I get nothing like this, not even an error.... could someone point me in the right direction?

2
  • I assume you are looking to dynamically bind which component to render, probably looking for this vuejs.org/v2/guide/components-dynamic-async.html Commented Jan 26, 2019 at 19:22
  • @Gowri how can I use that to load different views for the same component? Commented Jan 27, 2019 at 7:32

1 Answer 1

2

@Gowri pointed into the right direction. Your idea is to dynamically put components in the container.

This fiddle will show you the general idea of putting the specific name of the component to v-bind:is directive. Or shorthand :is.

I assume that you have all your templates defined and imported to the container component file. As a result, just assign them in components section and put the appropriate name to <component> tag.

List of locally registered components might look like:

components: {
 'client-1': Client1Template,
 'client-2': Client2Template
}

<component
    :is="getComponentName"
  ></component>

Your getComponentName could look like:

computed: {
    getComponentName: function () {
      return process.env.VUE_APP_CLIENT;
    }
  }

Update for dynamic import ( without registering the component )

To load the template without the registration of component you could use Webpack import:

<template>
    <component :is="component" v-if="component" />
</template>
<script>
export default {
    data() {
        return {
            component: null,
        }
    },
    computed: {
        loader() {
            if (!process.env.VUE_APP_CLIENT) {
                return null
            }
            return () => import(`themes/${process.env.VUE_APP_CLIENT}/assets/views/myComponent.vue`)
        },
    },
    mounted() {
        this.loader()
            .then(() => {
                this.component = () => this.loader()
            })
            .catch(() => {
                // show an error message or maybe load some default template
                this.component = () => import('themes/defaultClient/assets/views/component.vue')
            })
    },
}
</script>

Additionally, I'd suggest you take a look at Functional Component. It has an almost similar approach to what I've proposed but in Vue way: https://v2.vuejs.org/v2/guide/render-function.html#Functional-Components

Update after comments

<script lang="ts">
  import { Component } from "vue-property-decorator";
  import MyComponent from "@/components/MyComponent.vue";
  @Component({})
  export default class MyComponentClientName extends MyComponent {}
</script>

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

7 Comments

hm... from my understanding, this would be 2 different coponents? I don't want to repeat the component logic, (js nor css)... just template .. I want to retain the other logic
@DS_web_developer got it. Didn't notice that. I've updated my answer with dynamic Webpack import and link to Functional Components ( I haven't used them so my knowledge is restricted by documentation only )
Heya, great, thanks, that helped. The only problems is now passing the props that I have in the component to the vue, I have @Prop() item: any; among others and vue is giving me error now that item is not defined in the template
is it actually loading a whole new component or just the template in themes/..../MyComponent.vue?
@DS_web_developer I've added this part to answer. But in the original question, you didn't mention the params and extending.
|

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.