Pass data from Vue loop to laravel component - vue.js

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.

Related

vue - use same url multiple times with other anchor

In my web application I use the same url several times with other anchors. Is it possible to somehow "store" the baseurl somewhere?
My code looks like:
<a
class="link"
href="https://google.com/same/index.html#ancor"
target="_blank">
{{ $t("labelLearnMore") }}
</a>
https://google.com is always the same, can I shorten this somehow in vue that the code looks cleaner?
Thank you in advance!
Instead of the a tag, use the router-link provided by vue-router.
The code will be:
<router-link
to="/same/index.html#ancor"
target='_blank'
/>
For more informations take a look to the documentation
<a
class="link"
:href="baseUrl + '/same/index.html#ancor'"
target="_blank">
{{ $t("labelLearnMore") }}
</a>
or es2015
<a
class="link"
:href="`${baseUrl}/same/index.html#ancor`"
target="_blank">
{{ $t("labelLearnMore") }}
</a>
set baseUrl in your vue data

How to make Algolia instant search with Vue query records after page has loaded

I am working on a Gridsome application (SSG built with Vue). I added a search page and I've implemented the Algolia instant search with the autocomplete widget.
Gridsome by default lazy loads routes and renders the pages on the server-side, and since the instant search component I'm using does not support SSR, I wrapped it in a <ClientOnly> component.
The problem
When I navigate to /search it takes a while before I the components are rendered, this is because immediately I navigate to the page, the script to fetch the content is executed which blocks the rendering until it is finished. causing a bad UX.
The code
<div class="search-page-container">
<div class="search-field-container">
<h2><label for="search-field">Search</label></h2>
<ClientOnly>
<ais-instant-search :search-client="searchClient" :index-name="INDEX_NAME">
<ais-autocomplete>
<div slot-scope="{ currentRefinement, indices, refine }">
<input id="search-field" type="search" :value="currentRefinement" placeholder="what topic are you looking for?" #input="refine($event.currentTarget.value)" autocomplete="off" />
<div v-if="currentRefinement">
<h4>Articles</h4>
<div class="hits">
<ul v-for="index in indices" :key="index.label">
<li v-show="index.hits.length == 0"><em>No matches...</em></li>
<li>
<ul>
<li v-for="hit in index.hits" :key="hit.objectID">
<div>
<g-link :to="hit.slug"><ais-highlight attribute="title" :hit="hit"/></g-link>
<br>
<small class="post-description"><ais-highlight attribute="description" :hit="hit"/></small>
<!-- <hr> -->
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="space-top" v-else> <p> Type in the box to search for articles.. </p></div>
</div>
</ais-autocomplete>
</ais-instant-search>
</ClientOnly>
</div>
What I want
I want the queries to be made only when the user starts typing, that way, it doesn't block the rendering.

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).

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

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>

How do you add custom id attributes to div elements in Shopify Boundless theme?

I need to target a specific div in Shopify. I'm using Boundless Theme. I want to add a custom id attribute to this specific div. How can I do this?
The div I need to target is the 3rd div with class "product-item grid__item medium-up--one-third":
<div class="featured-collection" data-section-id="featured-collection" data-section-type="featured-collection-section">
<h2 class="visually-hidden">frontpage</h2>
<div class="grid grid--no-gutters grid--uniform collection-grid">
<div class="product-item grid__item medium-up--one-third">
<a class="product-item__link " href="/products/kaylava-candor-decaf-coffee-bean">
<img class="product-item__image" src="//cdn.shopify.com/s/files/1/1460/5816/products/candor-coffee-sm_grande.jpg?v=1485668871" alt="CANDOR DECAF COFFEE">
<span class="product-item__meta">
<span class="product-item__meta__inner">
<p class="product-item__title">CANDOR DECAF COFFEE</p>
<p class="product-item__price-wrapper"><span class="txt--emphasis">from</span> $15.99</p>
</span>
</span>
</a>
</div>
</div>
</div>
In Shopify you are able to edit the HTML by modifying the themes code.
The sample above looks like its either from the index.liquid template file or product-card.liquid under the snippets.
If you are able to locate the code within the template files then you can add an ID directly to the code.
Alternatively use JQUery Selectors and navigate down using the data-section-id="featured-collection" as a base.
Found a solution with help from Toby Mills!
In Boundless Theme, the "product_item grid_item" class is generated from the product-grid-item.liquid file.
Inside the top div, I added
id="home-{{ product.id }}"
Here is the final look
<div id="home-{{ product.id }}" class="product-item grid__item {{ grid_item_width }}" >
Now each div has a unique id that I can target with CSS!
<div id="home-8748279361" class="product-item grid__item medium-up--one-third" >
<a class="product-item__link " href="/products/kaylava-candor-decaf-coffee-bean">
<img class="product-item__image" src="//cdn.shopify.com/s/files/1/1460/5816/products/candor-coffee-sm_grande.jpg?v=1485668871" alt="CANDOR DECAF COFFEE">
<span class="product-item__meta">
<span class="product-item__meta__inner">
<p class="product-item__title">CANDOR DECAF COFFEE</p>
<p class="product-item__price-wrapper">
<span class="txt--emphasis">from</span> $15.99
</p>
</span>
</span>