vuejs Setting Dynamic path to template's src - vue.js

I have an vue application which I have divided in components kinda manner seen below.
What I want is to bind src property in <template> like below so that I could have a dynamic path every time a user asks for different template to get loaded.
The .ts file will have same code in use for every different template. which prompt me to ask this question.
Please suggest a solution to it. Or am I going into right direction or not to achieve this ?

One way to achieve dynamic templates being rendered is using dynamic component rendering:
App.vue:
<template>
<div>
<button #click="selectedComponent = 'app-quote'">Quote</button>
<button #click="selectedComponent = 'app-author'">Author</button>
<button #click="selectedComponent = 'app-new'">New</button>
<hr>
<component :is="selectedComponent"></component>
</div>
</template>
<srcript>
import Quote from './components/Quote.vue'
import Author from './components/Author.vue'
import New from './components/New.vue'
data: function() {
return {
selectedComponent: 'app-quote'
}
},
components: {
'app-quote': Quote,
'app-author': Author,
'app-new': New
}
</script>

Related

v-select component not loading into HTML

I am trying to create a basic site, where I need to select options from a dropdown menu. I am using the Select.vue from the vue-strap library to implement the same. However, the v-select component in not loading onto the html. Given below is the App.vue which inherits Select.vue from vue-strap:
<template>
<div>
<app-header></app-header>
<v-select v-model="selected" :options="['Vue.js','React']"></v-select>
<app-footer></app-footer>
</div>
</template>
<script>
import Header from './components/header.vue'
import select from '../node_modules/vue-strap/src/Select.vue'
import Footer from './components/footer.vue'
export default {
components: {
'app-header': Header,
'app-footer': Footer,
'v-select': select,
},
data() {
return {
}
},
}
</script>
<style scoped>
</style>
Given below are the errors that I am getting onto the web console:
I am unable to resolve these errors. Any help is appreciated.
:options="['Vue.js','React']"
Above line can be a big problem, since you are passing the static data and not assigning any variable you don't have to use :
: this actually a binding operator you should only use this when you are binding option to some variable
For eg:
data(){
return{
options:[['Vue.js','React']]
}
}
now inside your vue file, you can add
<v-select v-model="selected" :options=options></v-select>
If you dont want to declare variable then you can remove :
<v-select v-model="selected" options="['Vue.js','React']"></v-select>
Always make sure whatever you are passing to the component is declared inside the data
If you want to use computed make sure you declare it upfront before using it

Vue component not rendered on second visit

I have a Vue component that lists a bunch of clickable tags. When you click on a tag, it takes you to another page with a list of objects containing that tag.
The relevant parts of the component code are:
<template>
<div>
<h2>All Tags</h2>
<TagList v-bind:tags="tags"/>
</div>
</template>
...
<script>
import TagList from './TagList'
export default {
name: 'AllTags',
components: {
TagList
},
data () {
return {
tags: []
}
},
mounted () {
tags = // array loaded from a database
}
}
</script>
This all works fine when I initially view the page. However if I browse away from this list, e.g. by clicking on a single tag, and then browse back, I only see the <h2>All Tags</h2> header. Using the Vue debugger in the browser, I can see that the data are still there.
I'm using <router-view :key="$route.fullPath"> to control the overall app and suspect the problem lies with the keys somehow.
Can someone point me in the right direction here? How can I get the TagList component to render every time I visit that page of the app?
EDIT: Here's the code of the TagList component:
<template>
<div class="tags">
<Tag v-for="tag in tags" v-bind:tag="tag" v-bind:key="tag" />
</div>
</template>
<script>
import Tag from './Tag'
export default {
name: 'TagList',
props: ['tags'],
components: {
Tag
}
}
</script>
You can try removing v-bind all thought its not required to use, I've checked your code it seems to work fine after visiting a tag and going back, all tags are still rendered. You can take a look at this working sample .
https://codesandbox.io/s/vue-template-3tcs4?fontsize=14

How to use the contents of a Vue js component as are initially loaded and then bind them to a variable

We are looking to get the contents from the html (for example using a slot ) but we later (after mounting) want to bind this to a variable as one would do with a v-html.
In other words we want on initialization to have the contents being loaded as they appear in the slot and later this entire piece of content to be controlled by a binding variable like v-html (because it will be html content).
How to achieve this? without following any ugly solutions such as needing to pass the entire initial html content inside v-html attribute!
You can try like this
<template>
<custom-component>
<div v-if="html_variable" v-html="html_variable"></div>
<template v-else>
<!-- default content here -->
</template>
</custom-component>
</template>
<script>
export default
{
data()
{
return {html_variable: null};
}
}
</script>
How using v-html is ugly? Anyway just use a non-visible element to define your initial html. a <script ref="initHTML" type="text/html"> ... </script> might be a good option.
Define a data entry that should hold your HTML init:
data () {
return {
dHTML: '',
}
},
On created() update your initial html state using the ref
created() {
this.dHTML = this.$refs.initHTML.innerHTML;
},
Now you can have a pretty v-html="dHTML"

Nested single file components - vue.js with electron-forge

I am trying electron for the first time and I am blown away by it. I have hit a wall, though, when trying to use single file vue.js components using electron-forge. My problem is the following:
I create a project using the vue.js template and run it. Works and looks great. I have a single file page with an index file that looks like this:
<div id="test"></div>
</body>
<script>
import Vue from 'vue';
import Test from './test';
const app = new Vue(Test).$mount('#test');
app.text = "Electron Forge with Vue.js!";
</script>
So far, so good. It imports Test, which is a single file component and renders it.
Now, I would like to have other single file components nested in this main component. For example, I would like to have the following, in my app file called test.vue
<template>
<h2>Hello from {{text}}</h2>
</template>
<script>
import About from './About.vue'
export default {
components: {
appAbout: About,
},
data () {
return {
text: 'Electron'
}
}
}
</script>
Again, so far so good. I can run the app with no errors so the component is being imported.
Here comes my problem: if I now try to render the component using <appAbout></appAbout>, as I have done before in web apps with vue.js, I get the following error.
It basically says that I am not using a single root element in my component, which is really strange because my component looks like this:
<template lang="html">
<div>Hello from component</div>
</template>
<script>
export default {
}
</script>
<style lang="css">
</style>
I am stuck. Can someone please help?
So I have tried a few different things with no success, like using or even as the component names.
I also have tried these two ways of starting the vue:
The way you get with electron-forge
const app = new Vue(App).$mount('#app')
and the way I learned
new Vue({el: '#app', render: h => h(App)})
Nothing seems to work...
Define your component like this :
export default {
components: {
'app-about': About
}
}
Then use it in template like this (with kebab-case) :
<app-about></app-about>
About your compiling template error you need to wrap everything in test.vue in a root element :
<template>
<div>
<h2>Hello from {{text}}</h2>
<app-about></app-about>
</div>
</template>

Template are always fragment

I'm using Vue and Brunch in a small project, today I decide to add Vueify to make my components more concise.
But they are always seen has fragment instance so they are not rendered.
<template lang="pug">
div.sticker-container.sticker-xs-container.nav-top-sticker-animate#btn-about(v-bind:href="link")
span.sticker.sticker-xs.sticker-dark
span.sticker-txt.sticker-xs-txt(v-html="locales.btns.open")
span.sticker.sticker-xs.sticker-over.sticker-over-xs.sticker-light(v-show="opened")
span.sticker-txt.sticker-xs-txt.sticker-light-txt(v-html="locales.btns.close")
</template>
<script>
export default {
data(){
return {
disabled: false,
link: '#'
}
}
}
</script>
To use Vueify I simply add Vue-brunch to my project and I call this vue component like this:
import bar from './foo/bar'
Vue.component('sticker-bar', bar)
So, what i'm doing wrong ?
Try adding a surrounding div within your template. Like so:
<template>
<div>
<content></content>
</div>
</template>
Most times this will solve the fragment instance error.
For more detailed info: https://vuejs.org/guide/components.html#Fragment-Instance
I hope it helps!