Using Nuxt.js alias in component attributes - alias

I have a collection of images, audios and videos that should be displayed by a component one by one. All media is placed in assets sub-directories.
Given a simple Vue component for images like:
<template>
<img :src="src" :alt="src"></a>
</template>
<script>
export default {
name: "ImgDisplay",
props: ['src']
}
</script>
if I try to use it on some page:
<template>
<ImgDisplay src="~/assets/test.png"/>
</template>
the image is not actually displayed.
Vue component for MP3-files looks like this:
<template>
<vue-plyr>
<audio controls>
<source :src="src" type="audio/mp3"/>
</audio>
</vue-plyr>
</template>
<script>
export default {
name: "PlyrAudio",
props: ['src']
}
</script>
Then in document I have:
<template>
<div>
<article class="infobox">
<h6>Recording 1</h6>
<PlyrAudio src="~/assets/media/recording-1.mp3"/>
</article>
<article class="infobox">
<h6>Recording 2</h6>
<PlyrAudio src="~/assets/media/recording-2.mp3"/>
</article>
</div>
</template>
<script>
import PlyrAudio from "../components/media/PlyrAudio";
export default {
name: "PlyrAudioTest",
components: {PlyrAudio}
}
</script>
which does not work either, PlyrAudio component does not seem to find referenced mp3 files.
How can one use Nuxt.js aliases (~, ~~, #, ##) in component attributes? Is there some dedicated function to resolve ~ in <script> section of ImgDisplay and PlyrAudio or am I missing something?

Related

Components are not rendering in quasar project with no error

I created Vue 3, quasar project. everything worked fine till the moment I add new component. everything is rendering except the new component which I built and added it to the project. please help me with this problem if you can.
Here is my code:
index page:
<template>
<q-page class="flex flex-center">
<!-- section one-->
<SectionOne />
</q-page>
</template>
<script>
import { defineComponent } from "vue";
import SectionOne from "components/MainPage/SectionOne.vue";
export default defineComponent({
components: {
SectionOne,
},
name: "IndexPage",
});
</script>
Component:
<template>
<div class="q-pa-md q-gutter-md">
<div class="row justify-between">
<q-parallax src="https://cdn.quasar.dev/img/parallax2.jpg">
<h1 class="text-white">Basic</h1>
</q-parallax>
</div>
</div>
</template>
Not sure about your project structure, but try this (missing "./")
import SectionOne from "./components/MainPage/SectionOne.vue";
You can also import from the root 'src' like this:
import SectionOne from "src/components/MainPage/SectionOne.vue";

Vue layout with named slots

Is it possible?
I have something like this:
<template>
<my-layout>
<template #header>
Some header html goes here
</template>
Body html here
</my-layout>
</template>
<script>
import MyLayout from './MyLayout.vue'
export default {
layout: MyLayout,
components: {
//MyLayout
}
}
</script>
And template like that
<template>
<div>
<slot name="header"/>
</div>
<slot/>
</template>
The default slot works, but "header" slot doesn't display itself (unless using MyLayout as standard component).
I believe there is a problem with the closing tags on the template you have given and it should be like the following:
<template>
<div>
<slot name="header"> </slot>
</div>
</template>
After that, layout property only excepts strings or functions that return strings, so parent should be like the following:
<template>
<my-layout>
<template #header>
Some header html goes here
</template>
Body html here
</my-layout>
</template>
<script>
import MyLayout from "./MyLayout.vue";
export default {
layout: "MyLayout",
components: {
//MyLayout
}
};
</script>
I hope this solves your problem and have a nice day :)

Vue.js Issue: Prop doesn't change image v-bind:src

I've been trying to pass a prop to a component, which is a URL to an image for Section component to update v-bind:src of dom img tag, but somehow the image does not show up.
I can't see what's wrong.
File: App.vue
<template>
<div id="app">
<Section img="../assets/linux.png" />
</div>
</template>
<script>
import Section from "./components/Section.vue";
export default {
name: "app",
components: {
Section
}
};
</script>
File: Section.vue
<template>
<div>
<img :src="img" />
</div>
</template>
<script>
export default {
props: {
img: String
}
};
</script>
I suspect that the issue is due to the relative path you are using. I assume that ../assets/linux.png resolves to the right image URL with respect to App.vue, but it actually needs to resolve to the right image with respect to your <Section> component.
Based on what I can tell from the code you've shared, It seems like you can solve this by updating App.vue as follows:
<template>
<div id="app">
<Section img="../../assets/linux.png" />
</div>
</template>
...
I should, however, point out that you are getting absolutely no benefit from passing the image source as a prop like this. Since it is not bound to a reactive data property in App.vue, you may as well just omit that prop altogether.

Can't Embed Vue Component into an md-app using Vue Material

I have the following...
PageHeader.vue
<template>
<span> ${message} </span>
</template>
<script>
export default{
data: function(){
return {message: "asdsad" };
}
}
</script>
app.vue
<template>
<jg-header></jg-header>
</template>
<script>
import PageHeader from "./PageHeader.vue"
export default{
components: {
"jg-header": PageHeader
}
}
</script>
This works great so I want to convert it to using Vue Material so I change app.vue to this...
<template>
<md-app> <jg-header></jg-header> </md-app>
</template>
<script>
import PageHeader from "./PageHeader.vue"
export default{
components: {
"jg-header": PageHeader
}
}
</script>
It seems to create and render the Vue material component, however, the custom component doesn't show up anywhere. How do I get the Vue component to actually render inside the md-app
Update
Since there was some confusion, I create the Vue app I do call Vue.use (hence why it renders)
Vue.use(VueMaterial);
new Vue(App).$mount("#my-id");
<md-app> has specific content elements. Wrap your content in <md-app-content>.
Instead of:
<template>
<md-app> <jg-header></jg-header> </md-app>
</template>
Do:
<template>
<md-app>
<md-app-content>
<jg-header></jg-header>
<md-app-content>
</md-app>
</template>
Or, with a toolbar:
<template>
<md-app>
<md-app-toolbar> ... </md-app-toolbar>
<md-app-content>
<jg-header></jg-header>
<md-app-content>
</md-app>
</template>
Try wrapping the tags inside template with a div :
<template>
<div>
<md-app>
<jg-header></jg-header>
</md-app>
</div>
</template>

Components and Sub components

I'm new to Vue.js and I'm having a bit of trouble using components with sub-components. I have the following .vue files
app.vue
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider>
<skin></skin>
</slider>
</section>
</template>
slider.vue
<template>
<div id="slider-panel">
<h3>{{* heading}}</h3>
<div class="slider">
<slot>
Some content
</slot>
</div>
</div>
</template>
<script>
import skin from "./skin";
export default {
components: {
skin: skin
}
};
</script>
skin.vue
<template>
<div v-for="colour in colours">
<div :style="{ backgroundColor: colour }">
<img src="../assets/images/MIA.png"/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
heading: "Choose Skin Tone"
};
}
};
</script>
I'm trying to load the skin sub component into the component. Everything works well except for the skin sub component as it doesn't get compiled. I do not get any compile or vue related errors though. I also wanted to be able to have several instances of the slider component like this
app.vue
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider>
<skin></skin>
</slider>
<slider>
<foo></foo>
</slider>
<slider>
<bar></bar>
</slider>
</section>
</template>
I'm not sure what I am doing wrong.
I'm not 100% sure of what you want to achieve here, but to compile a component inside a component, you need to add the child component inside the parent's template, like this:
Slider.vue (I've simplified the structure):
<template>
<div id="slider-panel">
<h3>{{* heading}}</h3>
<skin></skin>
</div>
</template>
<script>
import skin from './skin'
export default {
components : {
'skin': skin
}
}
</script>
App.vue:
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider></slider>
</section>
</template>
Actually, if you add skin in the app's template inside of adding it in the slider component template, it gets included (and rendered) assuming that its scope is app, not slider. In order to add skin inside slider scope, it needs to be added to slider's template. Check this: https://vuejs.org/guide/components.html#Compilation-Scope
Some other things:
Use a hyphen-separated name for the components, with at least 2 words: <custom-slider> instead of <slider>, for example, following the Web Components API (otherwise it might collide with current or upcoming web components).
Slots are complicated to grasp, so read this carefully: https://vuejs.org/guide/components.html#Content-Distribution-with-Slots
Good luck!
Update:
If you want the slider component to be content agnostic and be able to insert anything you want inside it, you have two options (that I can think of):
Remove all the logic from the slider component and make skin a descendant from app. Then use slots in the slider component, as follows:
Slider.vue:
<template>
<div id="slider-panel">
<h3>{{* heading}}</h3>
<slot></slot>
</div>
</template>
<script>
export default {}
</script>
App.vue:
<template>
<section>
<menu></menu>
<h1>Create Your MIA</h1>
<div id="board"></div>
<slider>
<skin></skin>
</slider>
</section>
</template>
<script>
import skin from './skin'
export default {
skin: skin
}
</script>
If you know that the slider will always have a closed set of components inside, you can use dynamic components: https://vuejs.org/guide/components.html#Dynamic-Components
After some research I found this which refers to a is= attribute that will transclude the sub-component template
so in app.vue
<slider-component>
<div is="skin-component" v-for="colour in colours"></div>
</slider-component>
and then add child components