How to change fragment instances with multiple Components? - vue.js

Here, thats my Vue file.
The multiselect and classified-basic-info component are fragment instances.
How can I change it?
<template>
<div>
<div>
<multiselect :selected.sync="selected" :options="options"></multiselect>
</div>
<div>
<classified-basic-info :form.sync="form"></classified-basic-info>
</div>
<div>
KFZ |
Kleinanzeigen |
Job |
Immobilien |
<component :is="currentView"></component>
</div>
</div>
</template>

To avoid instance fragmentation component template must have root-level container element.
Put each templates content inside root DIV element and check it. Div must be inside template, not outside like in your example:
<div>
<multiselect :selected.sync="selected" :options="options"></multiselect>
</div>
Vue guide explains this.
Edit Add root div to your template:
<template>
<div>
<div>
<div>
<multiselect :selected.sync="selected" :options="options"></multiselect>
</div>
<div>
<classified-basic-info :form.sync="form"></classified-basic-info>
</div>
<div>
KFZ |
Kleinanzeigen |
Job |
Immobilien |
<component :is="currentView"></component>
</div>
</div>
</div>
</template>

Related

use v-slot to pass property to slots component - Vue 3

I´m struggeling with passing properties into a slots component.
Here some code to explain my problem:
App template:
<template>
<ModalContainer v-model="visibleModal">
<create-dir-modal />
</ModalContainer>
</template>
ModalContainer:
<template>
<div class="modal-container" v-if="modelValue" #click.self="close">
<slot :close="close" />
</div>
</template>
(close is a defined method here)
CreateDirModal:
<template v-slot="slot">
<div class="create-dir-modal-container">
<i class="button" #click="slot.close">close</i>
<div>
<i>folder</i>
<input placeholder="Name" v-model="name" />
<span></span>
<i class="button">done</i>
</div>
</div>
</template>
I am trying to execute the close method from the ModalContainer in the CreateDirModal.
Here is my problem: slot is not defined in CreateDirModal template.
Am I just using it wrong or is there a way to fix my problem?

Default slot or named slot not working on "router-view" in Vue 3

Passing a header component as a named slot into router-view. But router-view not exactly displaying it. Normally this was work in vue 2. But it's not with vue 3. Is the way doing it changed or is it impossible to do it now?
header component
<template>
<header id="g-header">
<figure>
<img id="logo"
src="#/assets/images/logo.jpg"
alt="The beautiful MDN logo.">
</figure>
<nav id="g-nav" class="flex justify-space-between">
<a v-for="(link, idx) in links" :key="idx"
class="flex justify-center align-center capitalize"
:href="link.val">{{ link.text }}</a>
</nav>
</header>
</template>
router-view component
<template>
<div id="moduleA" class="modules">
<router-view class="moduleA-children">
<template #header>
<app-header></app-header>
</template>
</router-view>
</div>
</template>
children view component
<template>
<div id="step1">
<slot name="header"></slot>
<div class="row">the named slot OR default slot not showing</div>
</div>
</template>
Is there a way to accomplish this? Or do I missing something here?
In Vue Router 4, <router-view> exposes the component to render as a v-slot prop, named Component, which would be used with the built-in <component> tag. You could pass any slots to the component within that <component> tag:
<router-view v-slot="{ Component }">
<component :is="Component">
<template #header>
<app-header></app-header>
</template>
</component>
</router-view>
demo

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

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>

Adding a content inside of a vue component

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.