Vue.js nested v-repeat: How to access parent $index inside child? - vue.js

I am unable to do this:
<ul>
<li v-repeat="candy: candies">
<ul>
<li v-repeat="flavour: candy.flavours">
{{ candy.$index }}
</li>
</ul>
</li>
</ul>
Any work around?

UPDATE 2: v-for now supports specifying an alias for $index: http://vuejs.org/api/#v-for That should allow you to avoid naming collisions on $index.
UPDATE: VueJS 1.0 has deprecated v-repeat in favor of v-for. The same solution applies though.
Try using $parent.$index to access an $index in a parent scope.

Related

Pass data from Vue loop to laravel component

I am having this issue and I can not find my way around it without duplicating lots of code.
I have an array of entries coming from an axios request. Everything will go in an ul.
If I am doing it like this, everything is ok:
resource-index.blade.php
<ul>
<li v-for="entry in entries" :key="entry.id" >
<div>
<div>
<a :href="entry.links.show">
<x-button-icon color="gray-400">
#include('partials.svg.outline-eye')
</x-button-icon>
<span class="ml-3">{{ __('View') }}</span>
</a>
</div>
<div>
<a :href="entry.links.edit">
<x-button-icon color="gray-400">
#include('partials.svg.pencil')
</x-button-icon>
<span class="ml-3">{{ __('Edit') }}</span>
</a>
</div>
</div>
</li>
</ul>
However, in case I want to try to extract some of that stuff in different components, the details I am sending from Vue no longer get passed to the component.
resource-index.blade.php
<ul>
<li v-for="entry in entries" :key="entry.id" >
<div>
<x-grid-list-item-button label="{{ __('View') }}" :href="entry.links.show">
<x-slot name="icon">
#include('partials.svg.outline-eye')
</x-slot>
</x-grid-list-item-button>
<x-grid-list-item-button label="{{ __('Edit') }}" :href="entry.links.edit">
<x-slot name="icon">
#include('partials.svg.pencil')
</x-slot>
</x-grid-list-item-button>
</div>
</li>
</ul>
And here is the grid-list-item-button.blade.php
<div>
<a href="{{ $href }}">
#if($icon)
<x-button-icon color="gray-400">
{{ $icon }}
</x-button-icon>
#endif
<span class="ml-3">{{ $label }}</span>
</a>
</div>
I already tried:
moving the href="entry.links.show" in a named slot;
passing the data with v-bind: v-bind:href="entry.links.show";
::href="entry.links.show"
Can someone please tell what am I doing wrong or at least point me in the right direction with this?
Thanks!
If I got you right: You are trying to pass data from Vue.Js to Laravel-Components. Unfortunately this is not possible. Blade gets processed on the server-side where Vue.Js is not yet available. So the variable entry.links.show do not yet exist in Laravel (only available on client-side) and therefore cannot be passed to the Laravel-Component. After the HTML got rendered by Blade and passed to the Browser, Vue.Js can pick it up and replicate your template for the v-for and generate your list. At this point your 'link'-variables get available.
Solutions:
You could extract your code to a Vue.Js-Component rather than a Laravel-Component. This would be interpreted on client-side.
An other solution would be to generate this list through Blade so you could use Laravel-Components.

Looping out slots?

In my vue template I have:
<ul>
<li>slide a</li>
<li>slide b</li>
....
</ul>
But I want to pass in each slide from the parent using a slot, so:
<carousel>
<img src="abc.jpg">
<img src="xyz.jpg">
</carousel>
But how can I loop out what is passed in to each li? So I want to end up with:
<ul>
<li><img src="abc.jpg"></li>
<li><img src="xyz.jpg"></li>
....
</ul>
Also I want to be able to pass in any dom element via the slot to the list element.
As Michael said, you can achieve this behavior via scoped slots.
In your carousel component, the template will look like this :
<ul>
// TODO : Add a :key with a unique identifier
<li v-for="item in items">
<slot name="item" :item="item">
{{ item }}
</template>
</li>
</ul>
And when using the component, you will do something like this :
<carousel :items="images">
<img #item="{ src }" :src="src">
</carousel>
Depending on your images data, you may need to get the source from another property.

Getting Error "Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key" in index.vue

I am new to vue.js. I have a simple index.vue which tries to connect to contentful and display the entries from contentful. My code in index.vue looks like this:
<template>
<div>
<!-- render data of the person -->
<h1>{{ person.fields.name }}</h1>
<!-- render blog posts -->
<ul>
<li v-for="post in posts">
{{ post.fields.title }}
</li>
</ul>
</div>
</template>
<script>
import {createClient} from '~/plugins/contentful.js'
const client = createClient()
However when I try localhost:3000 from my browser...it comes back with the following error:
ERROR in ./pages/index.vue
Module Error (from ./node_modules/eslint-loader/index.js):
C:\Users\admin\pdress\pages\index.vue
7:7 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
✖ 1 problem (1 error, 0 warnings)
I appreciate if someone can help me out to proceed further with my learning on vue.js please. Thanks in advance
What #ljubadr suggested is right. You need to do this:
<li v-for="post in posts" v-bind:key="post.id">
<!-- OR USE SHORTCUT NOTATION -->
<li v-for="post in posts" :key="post.id">
The reason has to do with performance. Attribute key helps Vue determine unique items in a list. Consider the example of sorting. If your UI has a sort button for posts, then your the order of items in post array will change. But does that mean Vue is going to re-render entire list? Of course not! Using :key it can determine if the item was already rendered on UI. It simply shuffles the DOM nodes and saves expensive rendering cycles.
Secondly, if you have complex components within your list when you are using v-for and :key is not provided, then whenever the list is changed or re-ordered, it simply changes the DOM but doesn't destroy existing components and that can cause local state mismatch. That is why it is must to have :key attribute.
Read Vue.js documentation for further information.
Note: Also remember that using v-for index for :key is a bad idea as it is not unique across your collection.
<template>
<div>
<!-- render data of the person -->
<h1>{{ person.fields.name }}</h1>
<!-- render blog posts -->
<ul>
<li v-for="post in posts" :key = "post">
{{ post.fields.title }}
</li>
</ul>
</div>
</template>
If this is not going to work use any unique field from your object for example if you have id in your object then,
:key = "post.id"
You must define a :key atribute for
v-for directive. And for <transition-group> tag.
for this case v-for you must explicit set,
<li v-for="(post, i) in posts" :key="i + 10">
{{ post.fields.title }}
</li>
If you noticed you can define max two argument in the v-for you must define the item (post) and can define the index of the post.

How can I implement ng-class-odd in Aurelia

I would like the odd table rows to bee colored. Angular has ng-class-odd and ng-class-even that works inside the scope of ng-repeat.
Can I somehow get the index of the repeat-for function in Aurelia?
There is $even and $odd properties that is available on the items in an repeat.for binding.
You could conditionally apply a class like this -
<ul>
<li repeat.for="item of items" class="${ $even ? 'my-class': '' }"></li>
</ul>

How to create multiple levels of indentation in Javadoc?

Suppose, that as part of documenting your code (Javadoc) you want to indicate that the relationships between elements using deep indentation.
How can I create a nested list as:
some element
some other element
yet some other element
<ul>
<li>Element</li>
<ul>
<li>Subelement...</li>
You can pretty freely use HTML inside javadoc comments.
Update: Because it came up, I tried
<ul>
<li>one</li>
<ul>
<li>one point one</li>
</ul>
</ul>
and get
one
one point one
I agree proper nesting is better.
The correct way is as follows:
/**
* <ul>
* <li>some element
* <li><ul>
* <li>some other element
* <li><ul>
* <li>yet some other element
* </ul>
* </ul>
* </ul>
*/
Although JavaDoc borrows from HTML, it isn't HTML, and you should omit the </li> tags, just as you should omit </p> tags.
The nested list should be within its own <li>. <ul> is not a valid child element of <ul>.
So your example would be:
<ul>
<li>some element</li>
<li>
<ul>
<li>some other element</li>
<li>
<ul>
<li>yet some other element</li>
</ul>
</li>
</ul>
</li>
</ul>