I want to implement vue component - tree. Each node doesn't know how to display itself, customer should know (see line 5). I want to setup scoped slots for parent node and for all children. But children data is not passed up to be displayed correctly from 3-rd level. Example https://codepen.io/vlapenkov/pen/gOpbxRG?editors=1011
<div id="app" class="jstree jstree-default jstree-default-medium">
<ul class="jstree-container-ul jstree-children jstree-no-icons">
<tree-item
v-for="(child, index) in treeData"
:item="child"
:is-last="treeData.length-1 === index"
:level="0"
>
<template scope="shape">
<div style="position:relative; display:inline-block;">{{ shape.name }}</div>
</template>
</tree-item>
</ul>
</div>
<template id="item-template" >
<li class="jstree-node" v-bind:class="className">
<i class="jstree-icon jstree-ocl" v-on:click="toggle"></i>
<a class="jstree-anchor" href="#" v-bind:class=" isSelected ? 'jstree-clicked':''">
<i class="jstree-icon jstree-themeicon"></i>
<span>{{item.name}}</span>
<slot v-bind="item"></slot>
</a>
<ul v-show="isOpen" class="jstree-children">
<tree-item
v-for="(child, index) in item.children"
:key="index"
:item="child"
:is-last="item.children.length-1 === index"
:level="level+1"
>
<slot v-bind="child"></slot>
</tree-item>
</ul>
</li>
</template>
You can pass through scoped slots like this:
<template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope"><slot :name="slot" v-bind="scope"/></template>
Related
Trying out vuedraggable and the items drag and sort.
<draggable :list="listRows" item-key="listID" class="list-group">
<template #item="{ element }">
<div class="list-group-item" >
{{ element.name }}
</div>
</template>
</draggable>
This works but if I add <transition-group>:
<draggable :list="listRows" item-key="listID" class="list-group">
<transition-group>
<template #item="{ element }">
<div class="list-group-item" >
{{ element.name }}
</div>
</template>
</transition-group>
</draggable>
I get the error:
draggable element must have an item slot
I can't find any examples of how to fix this error or any explanation.
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
I am using getuikit's tab component ( https://getuikit.com/docs/tab ) in my Vue-App:
Now I see that every tab is active, if I use v-for to iterate through an array.
<ul class=" uk-tab-left" uk-tab>
<li v-for="test in tests" id="test">{{ test }}</li>
</ul>
In my codepen example you can see, that the class uk-active is always inserted automatically:
https://codepen.io/spqrinc/pen/Ydzbez
Is there a possibility to change this behavior?
You can add a empty li element before the loop to make sure the active class will not be added to the others.
Don't forget to add a key to the loop and bind the id.
<div id="app">
<div>
<div uk-grid>
<div class="uk-width-1-4#m">
<ul class=" uk-tab-left" data-uk-tab>
<li></li>
<li v-for="test in tests" :key="test" :id="test">
{{ test }}
</li>
</ul>
</div>
</div>
</div>
</div>
<div id="app">
<div>
<div uk-grid>
<div class="uk-width-1-4#m">
<ul class=" uk-tab-left" data-uk-tab>
<template v-for="test in tests">
<li :key="test" :id="test">
{{ test }}
</li>
</template>
</ul>
</div>
</div>
</div>
</div>
in my case i create dynamic form (like todo app) in another components. i want accesibility for other actions. therefore i must set id or number each created element(div). when i add increment method console shows duplicate key error.
how can i add number or id each element?
For examples: this is 1. created element,
this is 2. created element,
this is 3. created element,
some codes:
methods: {
...mapActions(["setAdList"]),
ilanVer() {
this.alert = true;
let adListObj = {
adName: this.adName,
text: this.text,
province: this.province,
education: this.education,
solder: this.solder,
id: this.id
}
this.setAdList(adListObj);
this.id += 1;
console.log(this.id)
},
}
<template>
<!-- eslint-disable max-len -->
<div class="ad-box">
<h1 class="d-flex justify-content-center align-items-center mt-2">İlanlarım</h1>
<hr />
<div class="ilan-list">
<b-card :title=item.adName v-for="(item) in adList" :key="item.id" class="border border-info rounded w-50">
<b-badge class="ml-3">{{item.id}}</b-badge>
<p class="card-text">Aday Özellikleri: <span class="text-center">{{item.text}}</span> </p>
<p class="card-text">Şehir: {{item.province}}</p>
<p class="card-text">Eğitim: {{item.education}}</p>
<p class="card-text">Askerlik: {{item.solder}}</p>
<router-link to="/ilandetayi/:id">
<b-button class="btn-outline-success mr-2">İlanlarıma Git</b-button>
</router-link>
</b-card>
<hr />
</div>
</div>
</template>
You can use index when using v-for directive
In your case
v-for="(item, index) in adList" and then inside the block index will have values 0, 1, 2, ....
You can use Index item of v-for to define the unique id
v-for="(item, index) in adList" :key="index"
<template> <!-- eslint-disable max-len --> <div class="ad-box">
<h1 class="d-flex justify-content-center align-items-center mt-2">İlanlarım</h1>
<hr />
<div class="ilan-list">
<b-card :title=item.adName v-for="(item, index) in adList" :key="index" class="border border-info rounded w-50">
<b-badge class="ml-3">{{item.id}}</b-badge>
<p class="card-text">Aday Özellikleri: <span class="text-center">{{item.text}}</span> </p>
<p class="card-text">Şehir: {{item.province}}</p>
<p class="card-text">Eğitim: {{item.education}}</p>
<p class="card-text">Askerlik: {{item.solder}}</p>
<router-link to="/ilandetayi/:id">
<b-button class="btn-outline-success mr-2">İlanlarıma Git</b-button>
</router-link>
</b-card>
<hr />
</div> </div> </template
> Blockquote
I've been struggling with making vue transitions work.
I'm using vue2-animate along with vue to create some simple transition effect for when list items appear/disappear.
Here's the block:
<transition-group class="mt-2"
name="fadeLeft"
v-if="type == selectedType"
tag="ul">
<li class="mb-2" v-bind:key="category.name"
v-for="(category, index) in getCategoriesForType(type)"
#click="selectCategory(category)">
{{ category.name }}
</li>
</transition-group>
It doesn't add any effects when I try it. It simply shows/ hides the lists.
I've tested/confirmed that the animation is working in different component, but cannot figure out why the above code doesn't do any animations.
Here's the block that was working:
<ul class="list-group notes" v-if="notes.length > 0">
<transition-group name="fadeLeft">
<li v-for="(note, index) in notes" v-bind:key="note" class="list-group-item" v-on:remove="notes.splice(index, 1)">
<button class="close" #click="removeNote(index)"><span class="fa fa-times"></span></button>
{{ note.text }}
</li>
</transition-group>
</ul>