Adding a content inside of a vue component - vue.js

I have a vue component Jumbotron.vue:
<template lang="html">
<div class="jumbotron" style="border-radius:0px; color:#fff;">
<div class="container">
</div>
</div>
</template>
And other page component Main.vue:
<template>
<div class="root">
<navbar></navbar>
<jumbotron>
<h1 class="display-4">I want to add here, to the jumbotron's div container some h1 and paragraph</h1>
<p class="lead ">Like this paragraph</p>
</jumbotron>
<words></words>
</div>
</template>
But i cant add content to the jumbotron, because its wrong. I dont want to add content(p and h1) inside of the Jumbotron.vue, because i want to use Jumbotron.vue more than 1 time with different content inside it. Is this possible?

This is done with slots.
<template lang="html">
<div class="jumbotron" style="border-radius:0px; color:#fff;">
<div class="container">
<slot></slot>
</div>
</div>
</template>
Everything you put inside the jumbotron component in the parent will be rendered in the slot.

Related

V-FOR with background images

I'm trying to get a v-for cycle with background images. My intention is to have for columns each containing a different background image. Is there something wrong here? :(
Please note also photos it's an array imported with props. This is a component template.
<template>
<div class="row">
<div
v-for="photo in photos"
:key="photo"
class="col-3"
style="background-image: url({{photo.url}})"
>
Need to see photo here
</div>
</div>
</template>
<script>
export default {
props: ["photos"],
};
</script>
I'd use template literals with the :style shorthand for v-bind:style
<template>
<div class="row">
<div
v-for="(photo, index) in photos"
:key="index"
class="col-3"
:style="`background-image: url(${photo.url})`"
>
Need to see photo here
</div>
</div>
</template>
Refer to Binding Inline Styles
<div
v-for="photo in photos"
:key="photo"
class="col-3"
v-bind:style="{background-image: 'url(' + photo.url + ')'}"
>
Need to see photo here
</div>

Is this the right approach to create a component?

I made a view to show some contact information for the user:
<template>
<div v-for="user in users" class="user">
<div class="userInformation">
<img :src="user.photo" />
<div class="userName">
<h3>{{ user.age }}</h3>
<p>{{ user.gender }}</p>
</div>
</div>
<div class="button-wrapper">
<a href="#">
<button #click="$router.push(`/user/${user.id}`)">User Profile</button>
</a>
</div>
</div>
</template>
<style>
</style>
users is an array that holds all users which I fetch from the backend.
I want to create a component so that I can re-use the user card in other classes and don´t have to include the markup. I tried it the following way but I'm stuck at the button to redirect the user and the img because I don´t know how to use named slots there.
<template>
<div class="user">
<div class="userInformation">
<img />
<div class="userName">
<h3>{{ age }}</h3>
<p>{{ gender }}</p>
</div>
</div>
<div class="button-wrapper">
<a href="#">
<button>User Profile</button>
</a>
</div>
</div>
</template>
<script>
export default {
name: "UserCard",
props: [
"age",
"gender"
]
};
</script>
Another problem is that I have to re-create the fetch method for my users in other classes to access the user information. Would there be a better way of doing this?
// fetch user data from backend and create users array
...
<div v-for="user in users" :key="user.name">
<UserCard
:age="`${user.age}`"
:gender="`${user.gender}`"
/>
</div>
Is this the right approach to create a reusable component?
You're headed in the right direction for your component. If you wanted a named slot for the button you could use something like this.
Child Component
<template>
...
<slot name="button">
<!-- default/fallback content can be provided, if the parent does
not provide slot content the button-wrapper div will appear -->
<div class="button-wrapper">
<a href="#">
<button>Default Button</button>
</a>
</div>
</slot>
</div>
</template>
Parent
<div v-for="user in users" :key="user.name">
<UserCard
:age="user.age"
:gender="user.gender">
<template v-slot:button>
<div>some custom button here {{ user.phone }}</div>
</template>
</UserCard>
</div>
Also compilation scope (Vuejs v2 guide) is an important thing to keep in mind with slots - "Everything in the parent template is compiled in parent scope; everything in the child template is compiled in the child scope."
In terms of fetching your users, that's a separate issue. Look into something like Vuex or other ways of managing shared state if you find yourself constantly having to fetch users in various components

vuejs show html in component like reactjs

suppose we have a component like this.
<template>
<div class=" ">
<div class="flex-grow">{{title}}</div>
<div class=" p-5">
<!-- want to show here -->
</div>
</div>
<script>
export default {
props: ['title'],
mounted() {
console.log('Component mounted.')
}
}
</script>
i try this
<comp :title="'here'">
<h1> this is </h1>
</comp>
i want to show html b.w vue component tag, like we do in react.
how we can achieve this
If I understand the question, you're looking to create a component that can accept child elements. In order to do this, use <slot></slot> in your template where you'd like child elements to be inserted. Child elements can be other components or HTML.
See the reference for more thorough details.
In your example:
<template>
<div class=" ">
<div class="flex-grow">{{title}}</div>
<div class=" p-5">
<slot></slot>
</div>
</div>
</template>

Vue add or remove enclosing div

I have a html structure like this:
<template>
<div>
<div class="container">
<somecontent>
<someothercontent>
</div>
</div>
</template>
However, depending on the layout, I want to remove the container div so the structure looks like this:
<template>
<div>
<somecontent>
<someothercontent>
</div>
</template>
Note that the div is completely added or removed, not just the class name. v-if doesn't work here because it would also show or hide the content that is enclosed by the div. What's the simplest solution for that?
You can use
v-if ... v-else
<template>
<div v-if="condition">
<div class="container">
<somecontent>
<someothercontent>
</div>
</div>
<div v-else>
<somecontent>
<someothercontent>
</div>
</template>

Why always include "v-else" template block?

I have two templates on components and one flag.
<template v-if="mainPage">
<div class="col-md-12">
<h1>1 page</h1>
</div>
</template>
<template v-else>
<div class="col-md-12">
<h1>2 page</h1>
</div>
</template>
export default {
data () {
return {
text : '',
mainPage: true,
}
},
but default include second template. why?
First of all, when creating a vuejs you are only allowed one root element per component, so without the v-else part your component wouldnt work, unless you change template to div, and create one parent template:
If you don't want to use v-if you can just use v-show as:
<template v-show="mainPage">
<div class="col-md-12">
<h1>1 page</h1>
</div>
</template>
<template>
<div class="col-md-12">
<h1>2 page</h1>
</div>
</template>
This will not work for templates though. Because you can not have two templates in vuejs components