How can I update the accordion-item title using a v-for loop inside F7+Vue? - vue.js

How can I update the accordion-item title using a v-for loop inside F7+Vue ? I need each accordian-item title to be set to the Title of each object inside the myList array that is being looped over using the v-for.
Here is example below:
<f7-list-item v-for="value in myList" accordion-item title="{{value.Title}}">
<f7-accordion-content>
<f7-block>
<p>{{value.foo}}</p>
<p>{{value.boo}}</p>
</f7-block>
</f7-accordion-content>
</f7-list-item>
</f7-list>

Due to the time required for me to wrap my head around how I would use the current F7+Vue Accordion with a v-for to inject the title element... it seems that this is not possible. I could be wrong. I ended up resolving this by using the standard non f7+vue components...
example:
<div class="list accordion-list">
<ul>
<li class="accordion-item" v-for="value in myList">
<a href="#" class="item-link">
<div class="item-content">
<div class="item-inner">
<div class="item-title">{{value.Title}}</div>
</div>
</div>
</a>
<div class="accordion-item-content">
<div class="block">
<p>{{value.foo}}</p>
<p>{{value.boo}}</p>
</div>
</div>
</li>
</ul>
</div>

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.

Vue to render tr array recursively

I have to create collapsible tree with table data using bootstrap. This look the following way
<tr><td>Parent node1</td><td>...</td><td>...</td></tr>
<tr><td>Subparent node1.1</td><td>...</td><td>...</td></tr>
<tr><td>Subsupparent node1.1.1</td><td>...</td><td>...</td></tr>
<tr><td>Subsupparent node1.1.2</td><td>...</td><td>...</td></tr>
<tr><td>Subparent node1.2</td><td>...</td><td>...</td></tr>
<tr><td>Subsupparent node2.1.1</td><td>...</td><td>...</td></tr>
<tr><td>Subsupparent node2.1.2</td><td>...</td><td>...</td></tr>
I decided to create Vue component rendering on each level html with own data and collection of children via recursion:
<template id="tree-item">
<tr :key="currentNode.id">
<span #click="setExpanded(currentNode)">
<div style="display: inline-block;">
<span class="treegrid-indent" :style="{width: 15 * level + 'px'}"></span>
<span class="treegrid-expander fa" :class="currentNode.isExpanded ?'fa-chevron-down':'fa-chevron-right'">
</span>
</div>
{{level}} {{currentNode.id}}
</span>
</tr>
<tree-item v-for="item in currentNode.items" :currentNode="item" :level="level+1"> </tree-item>
</template>
But i get Vue error:Component template should contain exactly one root element.
Are there any ways to solve the task?
If you can relax your requirements to use a list instead of table then you can try something like this:
<div class="folder_container">
<ul class="no_list no_space">
<FolderTree :folder="folders" :level="0"/>
</ul>
</div>
And the FolderTree component's template looks like this:
<template>
<li>
<div>
<div class="folder_name">{{ folder.name }}</div>
</div>
<ul v-if="folder.child && folder.child.length > 0" class="no_list no_space">
<FolderTree
v-for="(fold,idx) in folder.child"
:key="fold.id"
:folder="fold"
:level="level + 1"
:last="1 + idx === folder.child.length"
/>
</ul>
</li>
</template>
If you need to use a table - then you will have to somehow transform your nested objects into a linear list/array of items. Otherwise you won't be able to overcome the limitation for only 1 root element in templates (unless you use render functions).

VueJS render once into an element

Is it possible to just render once into an element?
Suppose I have a contenteditable div, and only want to render the first value, then stop rerendering as the model changes. Here only the initial value of variable will be rendered.
<div contenteditable="true"> {{variable}} </div>
Use v-once
<div contenteditable="true" v-once> {{variable}} </div>
You can also wrap it with a <span>:
<div contenteditable="true">
<span v-once> {{variable}} </span>
</div>
refs:
https://v2.vuejs.org/v2/guide/components.html#Cheap-Static-Components-with-v-once
https://v2.vuejs.org/v2/api/#v-once
Or another solution is simply clone the variable and just don't modify it, for example if you call it readOnlyVariable:
<div contenteditable="true"> {{readOnlyVariable}} </div>

How to click a parent element using the child element for the following scenario

I am using selenium webdriver to automate. I have a special case below.
<div id = "A">
<div id = "container">
<div id="innercontainer">
<div>
<div id="ruleContainer">
<span id="rule">CNET</span>
<div id="name">CNET></div>
</div>
</div>
</div>
</div>
<div id = "A">
<div id = "container">
<div id="innercontainer">
<div>
<div id="ruleContainer">
<span id="rule">GNET</span>
<div id="name">GNET></div>
</div>
</div>
</div>
</div>`<div id = "A">
<div id = "container">
<div id="innercontainer">
<div>
<div id="ruleContainer">
<span id="rule">DNET</span>
<div id="name">DNET></div>
</div>
</div>
</div>
</div>`
Here I need to click on element A with text CNET... I am able to get to the child CNET but it is a dead element. So I need to click on anchor for element A having that particular child.
How can I do that? Is there a way? I know the solution for looping but my application refreshes so often and I encounter stale exception because of it. So could some one give me a better solution like navigating back to the parent and then to the sibling and click().
try this xpath:
//div[#id='A' and .//span[contains(text(), 'CNET')]]//a
it searches for the div with id = 'A' that has a span that contains the text 'CNET', from that div it selects the anchor-child-element