Wrapper element for for loop - vue.js

I'm currently expanding my horizon by trying out Vuejs.
I'm creating a navigation with data coming from my Vue instance, and I have the following code:
<ul class="nav">
<li class="nav-item" v-for="navLink in navLinks" :key="navLink.id">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</ul>
Now even though this works perfectly fine, I have seen the following two examples in videos instead:
<ul class="nav">
<template v-for="navLink in navLinks">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</template>
</ul>
<ul class="nav">
<div v-for="navLink in navLinks" :key="navLink.id">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</div>
</ul>
I'm asking myself which one of these is best practice.
Now from what I've learned, one should always (if possible) set a :key in a for loop. This is not possible on the tag, therefore I would think this option is the worse.
But what about option 3 and mine? Is there any difference? Is it just personal preference or is there an actual reason on why to choose one or the other.
Ty

The only difference I spot between the first and the third options is that you'd wrap each list item in an additional div. You don't need those wrappers unless you want to use this nesting for styling purposes.
Your example is perfectly fine. Just make sure ids you use for keys are unique.
Also avoid using v-if and v-for on the same element and rather add v-if on the parent

I think you should always put a key property in your for loop.
Say you have nothing to work with for an ID (some item.name could potentially be duplicated?) just use this:
<div v-for="(item, index) in items)" :key="index">
{{ item.name }}
</div>
index in this case is just the index of the items array.

So yours will be rendered like:
<ul class="nav">
<li class="nav-item" :key="navLink.id">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
...
<li class="nav-item" :key="navLink.id">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</ul>
Whereas the third one will be:
<ul class="nav">
<div :key="navLink.id">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</div>
...
<div :key="navLink.id">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</div>
</ul>
I would say it's a bit verbose to wrap a <li> inside a <div> in each one of them.

Yours is fine, all of them indeed are going to work well, but the third one may have problems with custom css, since it's a wrapper for the tag.
The template is an alternative as it is stated in the docs.
You've set the key at the li tag, as long as you're following the guide for mantaining state with keys, it's fine.

Related

vuejs dynamically bind text in class attribute

I am trying to dynamically change the text of an fa icon depending on what an object in the data (iterating in for loop) contains:
<ul id="example-1">
<li v-for="item in cards" :key="item.id">
<i class="fa fa-cc-{{item.brand}} fa-2x" style="color:black"></i> {{ item.brand }}
</li>
</ul>
This doesn't seem to work
You can make class as dynamic attribute as below
:class="`fa fa-cc-${item.brand}`"
I suppose that would be the correct way of doing it (string concatenation):
<ul id="example-1">
<li v-for="item in cards" :key="item.id">
<i :class="'fa fa-cc-'+item.brand+' fa-2x'" style="color:black"></i> {{ item.brand }}
</li>
</ul>
or different syntax with ECMAScript 6 template literals:
<ul id="example-1">
<li v-for="item in cards" :key="item.id">
<i :class="`fa fa-cc-${item.brand} fa-2x`" style="color:black"></i> {{ item.brand }}
</li>
</ul>
You can see that I used dynamic class binding.

How can I use a v-for value in to nuxt link?

I have a loop that loops through an associative array that has text with links
links: {'Amount' : '/about', 'Contact' : '/contact'}
How can I use the value from my for loop in my nuxt-link? So to="value"?
<ul class="link">
<li v-for="(link, text) in links" :key="text" :value="link">
<nuxt-link to=link>{{key}}</nuxt-link>
</li>
</ul>
Your code is almost correct. In order to use your JavaScript objects you just have to use model binding just like the following.
<ul class="link">
<li v-for="(link, text) in links" :key="text" :value="link">
<nuxt-link :to="link">{{key}}</nuxt-link>
</li>
</ul>
Please note the :to="link".
Try this :
<ul class="link">
<li v-for="(link, index) in links" :key="index">
<nuxt-link :to="link"> {{ index }}</nuxt-link>
</li>
</ul>

How do I toggle (hide/unhide) child elements of dynamically added components with v-for

The following renders a header text and some child elements.
What I would like to accomplish is that the child elements toggle (hide/unhide) when the header is clicked. So in below example, when Spanish01 is clicked, all its children should be hidden and when its clicked again the should reappear.
I tried to find a similar case on the internet but could not find any. All help is welcome
<div id="dashboard">
<ul class="collection with-header">
<li class="collection-header"><h4>Cards</h4></li>
<li v-for="card in cards" v-bind:key="card.id" class="collection-item">
<div class="chip">{{card.group_name}}</div>
<ul class="collection with-header">
<li v-for="(value, index) in card.group" v-bind:key="index" class="collection-item">
<ul>
<li>
front: {{value.front}}
</li>
<li>
back: {{value.back}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
You can simply put an extra variable on each of your cards. Then you can do something like this:
<div id="dashboard">
<ul class="collection with-header">
<li class="collection-header"><h4>Cards</h4></li>
<li v-for="card in cards" v-bind:key="card.id" class="collection-item">
<div class="chip" #click="card.shown = !card.shown>{{card.group_name}}</div>
<ul class="collection with-header" v-show="card.shown">
<li v-for="(value, index) in card.group" v-bind:key="index" class="collection-item">
<ul>
<li>
front: {{value.front}}
</li>
<li>
back: {{value.back}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Obviously, you have to alter your variable cards so it contains the shown attribute by default. As an alternative, you can set up a different variable that contains the shown status and use some unique id to look up the value instead.

Can I use v-if and v-for outside HTML tag?

The point is that if the condition is satisfied I should assign whole list to a variable, otherwise I need to iterate through list and assign element by element.
<ul>
<li v-if="flag = true">
<myVueComponent
v-bind:list="LIST">
</myVueComponent>
<v-else v-for="item in LIST">
<a v-else :href="url+item.name">#{{item.name}}</a>
</li>
</ul>
If this is not valid code, then could I use v-if inside one <li> tag and v-else inside another <li> tag? In that case I would also use v-for in that tag.
Basically, yes, you could use it inside v-if inside one list element and v-else inside another:
<ul>
<li v-if="flag">
<myVueComponent
v-bind:list="LIST">
</myVueComponent>
</li>
<li v-else v-for="item in LIST">
<a :href="url+item.name">#{{item.name}}</a>
</li>
</ul>

Multiple link dropdown issue in materializecss

I am using materialize css 1.0.0-rc.2. I am having issues in dropdown. Same dropdown is linked to navbar and sidenav but only one of them working and next thing is it should come below the navbar or link when hovered or clicked.What should I do please help?
I think it won't work for same dropdown structure in both Navbar and Sidebar. Making two dropdown structure can solve your problem.
<nav>
<div class="nav-wrapper">
Logo
<a href="#" data-target="mobile-demo" class="sidenav-trigger">
<i class="material-icons">menu</i>
</a>
<ul class="right hide-on-med-and-down">
<li>
Sass
</li>
<li>
Components
</li>
<li>
<a class="dropdown-trigger" href="#!" data-target="dropdown1">Dropdown
<i class="material-icons right">arrow_drop_down</i>
</a>
</li>
</ul>
</div>
</nav>
<ul id="dropdown1" class="dropdown-content">
<li>
one
</li>
<li>
two
</li>
<li>
three
</li>
</ul>
<ul id="dropdown2" class="dropdown-content">
<li>
one
</li>
<li>
two
</li>
<li>
three
</li>
</ul>
<ul class="sidenav" id="mobile-demo">
<li>
Sass
</li>
<li>
Components
</li>
<li>
<a class="dropdown-trigger2" href="#" data-target="dropdown2">Dropdown
<i class="material-icons right">arrow_drop_down</i>
</a>
</li>
</ul>
<script>
$(document).ready(function () {
$(".dropdown-trigger").dropdown({
hover: true
});
$(".dropdown-trigger2").dropdown();
$('.sidenav').sidenav();
});
</script>