VueJs v-for how to check list undefined before continue - vue.js

Refer to the template below, how to add condition to make sure the menu is not undefined inside the v-for attribute?
I've tried v-for="menu?item in menu.items:[]" and v-for="item in menu?.items" but neither works.
<div v-for="item in menu.items">{{item.text}}</div>

Put the div with the v-for directive within a <template> that checks for menu via v-if:
<template v-if="menu">
<div v-for="item in menu.items">{{ item.text }}</div>
</template>
This way, the div inside the template won't be rendered if menu does not exist.
If you really want the check within the v-for statement, like you are attempting, it would look like this:
<div v-for="item in (menu ? menu.items : [])">{{ item.text }}</div>

Related

Passing slots through from Parent to Child Components

I have built a user-defined component (async-select) on top of another component (vue mutliselect) like this:
https://jsfiddle.net/2x7n4rL6/4/
Since the original vue-multiselect component offers a couple of slots, I don't want to loose the chance to use them. So my goal is to make these slots available from inside my custom component. In other words, I want to something like this:
https://jsfiddle.net/2x7n4rL6/3/
But that code oes not work.
However, if I add the slot to the child component itself, it works just fine (which you can see from the fact that options become red-colored).
https://jsfiddle.net/2x7n4rL6/1/
After surfing the web, I have come across this article, but it does not seem to work
Is there any way in VueJS to accomplish this ?
Slots can be confusing!
First, you need a template element to define the slot content:
<async-select :value="value" :options="options">
<template v-slot:option-tmpl="{ props }">
<div class="ui grid">
<div style="color: red">{{ props.option.name }}</div>
</div>
</template>
</async-select>
Then, in the parent component, you need a slot element. That slot element itself can be inside of another template element, so its contents can be put in a slot of its own parent.
<multiselect
label="name"
ref="multiselect"
v-model="localValue"
placeholder="My component"
:options="options"
:multiple="false"
:taggable="false">
<template slot="option" slot-scope="props">
<slot name="option-tmpl" :props="props"></slot>
</template>
</multiselect>
Working Fiddle: https://jsfiddle.net/thebluenile/ph0s1jda/

How to dynamically insert a template into another template

New to VueJS... I have a component that I want to pass other components into based on the selection made in a dropdown. I have a main template that will always be rendered on the screen, part of which has a dropdown. When I make a selection in that dropdown I want to have a div inside that main component with an ID (or some other identifying property) and push another template inside of it. I'm thinking that a slot does the opposite of what I want..
Original Template:
<div class="search-field-with-label-container">
<el-select v-model="serviceType">
<el-option
v-for="serviceType in serviceTypes"
:key="serviceType.id"
:value="serviceType"
>{{ serviceType }}</el-option>
</el-select>
<div id="thisIsWhereIWantMyOtherTemplateToRender"
</div>
Second template:
<template>
<h1>this is the other template</h1>
</template>
You can use dynamic components with the keep-alive tag.
<keep-alive>
<component v-bind:is="selectedComponent"></component>
</keep-alive>
Documentation is here.

Custom elements in iteration require 'v-bind:key' directives

In my Nuxt app I have the following line that triggers the error mentioned in the title of this question:
<template v-for="(project, index) in existingProjects">
<span :key="project.projectId"></span>
I tried to have the :key attribute on the template element and I also tried to use just index as the key, to no avail.
Any idea?
There are multiple ways to solve your problem :
You want to iterate on a template :
You have to put a key on all elements in your template because you can not put a key on a template: <template> cannot be keyed. Place the key on real elements instead.
<template v-for="(project, index) in existingProjects">
<span :key="project.projectId">foo</span>
<div :key="project.projectId">bar</div>
</template>
You can iterate on something else than a template : You just put the key on the parent html tag.
<div v-for="(project, index) in existingProjects" :key="project.projectId">
<span>foo</span>
<div>bar</div>
</div>

VueJS: read div content from its id

In my first example, I have in my component's template:
<div id="hello">hello world</div>
When console.log(this.$refs['hello']) is called in myMethod(), I get undefined in the console.
In my second example, I have:
<div v-for="item in data">
<div :id="'hello-'+item.id">hello {{ item.id }}</div>
</div>
When console.log(this.$refs['hello-1']) is called in myMethod(), I also get undefined in the console.
What's wrong in my code ?
You cannot get element with refs by giving that element id. You should bind ref to that element. Here is an example:
<div v-for="item in data" :key="item.id">
<div :id="'hello-'+item.id" :ref="'hello-'+item.id">hello {{ item.id }}</div>
</div>
And also don't forget to bind key to your iterating elements with v-for

How to use v-if and v-else without any html tag or else

List item
<ul>
<li>language</li>
< v-if= "tree()"> //which tag I may use or any other process
<li>home</li>
<li>about</li>
<>
< v-else> //which tag I may use or any other process
<li>accounts</li>
<li>listing</li>
<>
</ul>'
In the V-if which html tag i may use or any other vue.js process to work with this.
You can use template:
<template v-if="condition">
</template>
<template v-else>
</template>
Template will not be rendered in the browser. But it will parse the contents inside of this to the html.
you can sometimes use the <slot> element to make what you want. Have a look at the slot documentation here