pass router params to component object - vue.js

I have view and I want to load svg based on router params, I have installed vue-loader and it is working if I hard code it.
<template>
<div>
<suit/>
</div>
</template>
<script>
export default {
components:{
suit: ()=>import('../assets/svg/'+Param+'.svg')
}
}
</script>
<style>
</style>
This is what I have. Instead of Param I want to get this.route.params, but when I try this I get undefined which is logical because components wrapper is object. Is there a way to pass a variable here or must I redo the whole thing?

Instead of this.route.params, within a component you should be using this.$route.params. Vue Router Docs.

Related

Does defineProps in script setup automatically create a local property of the defined prop?

When we pass a prop to a component and define that prop from child component with defineProps a property somehow is created and accessible from child components template.
parentComponent.vue
<template>
<child-component v-model="product">
</template>
<script setup>
import childComponent from "./childComponent.vue"
</script>
childComponent.vue
<template>
{{ product }}
</template>
<script setup>
const props = defineProps(['product'])
</script>
Here in childComponents template, the product can be accessed without needing to use props.product or toRef it. I know that script setup automatically injects the used props but I could not find any info (in docs) that the defineProps does some too. Is there any info about that.
According to this section :
The script is pre-processed and used as the component's setup() function, which means it will be executed for each instance of the component. Top-level bindings in <script setup> are automatically exposed to the template. For more details
Knowing that props are unwrapped directly inside the template and also the refs are used without .value.
If you want to reference some prop inside the script you should use props.product like in this example :
<script setup>
const props = defineProps(['product'])
const total=computed(()=>props.product.quantity*props.product.unity_price))
</script>
if the prop is only accessed by template you could get rid off const props just call the macro defineProps :
<template>
{{ product }}
</template>
<script setup>
defineProps(['product'])
</script>

Instantiating Vue components using only string

I have a string saved as a variable in javascript that contains both the <template> and <script> tags that could be saved into single file components in vue. Here is an example:
<template>
<div>
{{myVar}}
<button #click = "change(1)">Increment</button>
<button #click = "change(-1)">Decrement</button>
</div>
</template>
<script>
export default{
data(){
var randomVar = Math.round(10*Math.random());
return {
myVar: randomVar
}
},
mounted(){
this.change(12);
},
methods:{
change(num){
this.myVar += num;
}
}
};
</script>
Is there a way to instantiate said string as a vue component without having to save it as a single file component or separating the data, methods and other lifecycle hooks?
The HttpVueLoader can load .vue files directly in the browser - you can look at the source code and try to modify it to accept the string directly instead of fetching it from an URL.
Additionally, you may want to take a look at the Client-Side Vue project - it avoids the building step for SFC so you can use your .vue components directly in the browser.

Component rendering just the element name not the template contents

I have just started with Vue and am having an issue where the component isn't rendering for me.
<template>
<div>
<GalleryCollectionBlueBottles />
</div>
</template>
<script>
import GalleryCollectionBlueBottles from '#/components/collections/GalleryCollectionBlueBottles.vue'
export default {
name: 'GalleryCollections'
}
</script>
When I inspect the page in a browser all I see is an element with the component name, not the contents of the component as usual.
The component above is called GalleryCollections and the component I'm importing is called GalleryCollectionBlueBottles.
Hope someone can help, also hoping this is something simple I've overlooked :)
You need to also declare the component inside your script tag within the keyword components{ ... } like;
<script>
import GalleryCollectionBlueBottles from '#/components/collections/GalleryCollectionBlueBottles.vue'
export default {
name: 'GalleryCollections',
components: {
GalleryCollectionBlueBottles
}
}
</script>

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>

How to preserve custom component tag names in Vue.js

I'm using Vue's single-file component spec (*.vue) for custom components in my application. Together with rollup and rollup-plugin-vue, I have observed the output in the DOM, for custom components I have written, to be composed of the equivalent html elements.
For example:
component-a.vue
<template>
<span>Hello World</span>
</template>
<script>
export default { name: 'component-a' };
</script>
component-b.vue
<template>
<component-a></component-a>
</template>
<script>
import ComponentA from './path/to/component-a.vue';
export default { name: 'component-b', components: { ComponentA } };
</script>
The above example, if component-a is added to the Vue mount component, will render to a the sum of the two component's template contents in the DOM, which in this case is simply a span element:
<span>Hello World<span>
Is it possible to achieve a rendered output in the DOM like the snippet below, such that custom elements' templates are represented in the DOM by tags which preserve their tag names?
<component-b>
<component-a>
<span>Hello World</span>
</component-a>
</component-b>
Inside your component-a.vue you should be able to achieve that by including some html code within your <template> tag as follow
component-a.vue:
<template>
<customelement>
// Other stuff
</customelement>
</template>
In this way you will be able to call your component-a from anywhere in your app, and to render an element named customelement.
Ideally you should use this "trick" to render standard HTML5 elements, otherwise you might see some error in your vue app console. Let me know how it goes.
Referring to the Vuejs documentation
https://v2.vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats
It should be noted that this limitation does not apply if you are
using string templates from one of the following sources:
String templates (e.g. template: '...')
Single-file (.vue) components
<script type="text/x-template">
If you use Vuejs like the examples above you won't get the result you wanted. So if you render your components in other ways you should get the result you wanted.