Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 months ago.
Improve this question
I have a parent layout component for my Vue app which renders various child components, based on Vue router. I want to give some child components padding, but not others. How can I do this? Obviously, one way is to just apply the padding in the child components themselves, but this means lots of duplication of the padding code. What I'd really like is some way for the child component to tell the parent component whether it needs padding before rendering, so the parent component can apply the padding or not before it renders.
I think the best approach is to do it in the child component. If you don't want to repeat your code you can add a class and add the padding via css to that class.
The best way would be to write a component if it does not already exist and add a prop to it. Prop will decide which component requires padding.
I ended up using a dynamic layout component mechanism, where each child component defines which layout it wants by wrapping its template in the appropriate helper component:
App.vue
<script setup>
import { shallowRef } from 'vue';
import { RouterView } from 'vue-router';
import Navbar from '#/components/Navbar.vue';
const layout = shallowRef('div');
</script>
<template>
<Navbar />
<component :is="layout">
<RouterView #update:layout="(x) => { layout = x; }" />
</component>
</template>
Child.vue
<script setup>
import LayoutBoxed from '#/components/Layout/LayoutBoxed.vue';
</script>
<template>
<LayoutBoxed>
<h2>Child component</h2>
<div>Hello world</div>
</LayoutBoxed>
</template>
LayoutBoxed.vue
<script setup>
import { onBeforeMount } from 'vue';
import ImplLayoutBoxed from './ImplLayoutBoxed.vue';
const emit = defineEmits(['update:layout']);
onBeforeMount(() => {
emit('update:layout', ImplLayoutBoxed);
});
</script>
<template>
<slot />
</template>
ImplLayoutBoxed.vue
<template>
<div class="container-fluid mt-3 border border-2 rounded" style="background-color: #e3fff9; border-color: #7defb7 !important;">
<div class="p-3">
<slot />
</div>
</div>
</template>
Related
i'm new of this framework :(
the problem is here because i've tried to put the component in another page and work it.
It sign error the component
this is my index.vue page
If you're using nuxt2.0, you should wrap them in a container but this is not needed in nuxt3.0.
<template>
<main>
<navbar />
<slideshow />
</main>
</template>
If this is nuxt2.0, then you should also import the component and register it but you haven't done it here. The path you've given to the component is not correct also.
<script>
import Slideshow from '~/components/slideshow.vue';
export default {
components: { Slideshow }
}
</script>
You need to wrap the into a div or any other tag (to not have multiple tags at the root of the template) like that
<template>
<div>
<navbar></navbar>
<slideshow></slideshow>
</div>
</template>
And you can also skip the import part because Nuxt is already doing that for you as explained here: https://nuxtjs.org/tutorials/improve-your-developer-experience-with-nuxt-components/
I would like to have a component that can have another component placed into it. I'm struggling to find how this can be achieved.
If I pass a component in it doesn't get displayed. I'm assuming I need to specify it in the component however I can't find how in the documentation.
E.g.
<component-that-allows-nesting>
<nested-component/>
</component-that-allows-nesting>
What needs to be added to my component to allow it to accept a nested component?
Vuejs support nested component like Base Component and you can use it. if you want send data from parent component to child component you can use props.
for example
//parent-component
<form>
<base-input />
<base-button>
add form
</base-button>
</form>
//child-component
//BaseInput.vue
<input type="text" placeholder="userName" />
//BaseButton.vue
<button #click="submitForm" >
<slot></slot>
</button>
Here is an example for vue3 carousel.
You should import nested component
You should add this component in components
Use it as nested component
<template>
<carousel :items-to-show="1.5">
<slide v-for="slide in 10" :key="slide">
{{ slide }}
</slide>
</carousel>
</template>
<script>
import { Carousel, Slide } from 'vue3-carousel';
export default {
name: 'App',
components: {
Carousel,
Slide,
},
};
</script>
So I'm creating a relatively large website using Vue and Vue-router and different pages require different navigation bars (each custom components rendered on top of the page)(and some pages don't have a navbar at all) and currently I'm using a similar format to this:
<template>
<div>
<div v-if="firstNavbar">
<FirstNav />
<div>
<div v-if="secondNavbar">
<SecondNav />
</div>
<router-view />
</div>
</template>
But re-rendering the entire page for every routing event just because the navbar changed seems a bit inefficient, and I was wondering what I could do to remedy this.
Any help would be appreciated, thanks.
I would suggest the use of <keep-alive> element to cache the navbars. Try this
APP.vue
<template>
<keep-alive>
<component :is="getConditionallyRenderedNavbar"></component>
</keep-alive>
<router-view />
</template>
<script>
import firstNavbar from './firstNavbar.vue';
import secondNavbar from './secondNavbar.vue;
export default{
components:{
firstNavbar,
secondNavbar
},
computed: {
getConditionallyRenderedNavbar() {
return firstNav //or second nav or no nav
}
}
}
</script>
To find out more, check here
I'm trying to bind a custom attribute value in my Vue template. How can I do this?
(EDIT: The following code actually binds correctly. A third party library (Foundation) was interfering with the binding. Leaving the question up as it may be useful to others.
<template>
<span v-bind="{ 'aria-controls': inputControlId }"></span>
<input v-bind="{ 'id': inputControlId }">
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
#Component
export default class Slider extends Vue {
inputControlId = "TheBourneId";
}
}
</script>
The common syntax for binding attributes is
<template>
<span v-bind:aria-controls="inputControlId"></span>
<input v-bind:id="inputControlId">
</template>
There is also a shorthand.
<template>
<span :aria-controls="inputControlId"></span>
<input :id="inputControlId">
</template>
You can bind multiple properties at once using the syntax in your question, it's just not commonly used outside class or style, especially for single attributes.
It sounds like the real issue was your CSS framework.
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