Let's say I have the following case
<div class="entry">
<img src="image1.png">
</div>
<div class="entry">
<a href="#mylink">
<img src="image2.png">
</a>
</div>
Now, items needs to be iterated, using depending on a condition:
<div class="entry" v-for="o in items">
<a :href="o.url" v-if="o.url != ''">
<img :src="o.image">
</a>
<img :src="o.image" v-else>
</div>
With items = [{url: '', image: 'image1.png'}, {url: '#mylink', image: 'image2.png'}] this will correctly render to the same snippet from above:
<div class="entry">
<img src="image1.png">
</div>
<div class="entry">
<a href="#mylink">
<img src="image2.png">
</a>
</div>
But as you can see, I'm copy-pasting the <img> tag for the v-if directive. In this case I guess it's simple enough, but I want to know if there a more DRY approach.
I'm looking for something like:
<div class="entry" v-for="o in items">
<a :href="o.url" v-if-always-render-children="o.url != ''">
<img :src="o.image">
</a>
</div>
Which should render to the same snippet. Of course the directive v-if-always-render-children doesn't exists.
How to avoid declaring the <img> tag (and possible children tags) more than once?
v-else is fine, if you're really concerned about it and are worried about the size of the content, then make that content a component.
alternatively you can use render functions or jsx, but unless this thing gets quite a bit more complex, v-else is just fine
Related
I created a recipe website, you can find it here https://hungry-vegetarian.com/.
The tab on the index page is a vue instance. I'm trying to create a search bar that is also a vue instance.
The problem occurs when I try to display searched recipes on the index page. It just shows the search result on top of the search bar.
Ideally, only searched recipes should appear on the tab just like they are now but without any indications on top of the tab like Breakfast, Salad, Bakery, etc.
I don't know how to make two objects work together. For now, they work separately without communicating with each other.
SEARCH
<div id="search">
<div class="main-search">
<h1 class="search-question">What are you in the mood for?</h1>
<div class="search-box">
<input type="text" v-model="searchQuery" class="input-search" placeholder="Bread">
<button class="btn-search"><i class="fa fa-search"></i></button>
</div>
</div>
<div class="container">
<div class="recipe" v-for="post in filteredList">
<div v-if="searchQuery">
<a v-bind:href="post.url" class="recipe-card__card-link" target="_blank">
<img v-bind:src="post.image" alt="" class="recipe-card__image"/>
<div class="recipe-card__text-wrapper">
<h2 class="recipe-card__title">{{post.name}}</h2>
<div class="recipe-card__details-wrapper">
<p class="recipe-card__excerpt">{{post.body}}</p>
<a v-bind:href="post.url" class="recipe-card__read-more">Read more <i class="fa fa-arrow-right"></i></a>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
tab
<main id="tab">
<header>
<nav>
<ul>
<div id="arrow">
<span></span>
<span></span>
<span></span>
</div>
<li v-for="(tab, tabName) in tabs" :key="tabName">
<button class="tab" #click="setTabActive(tabName)" :class="{'active': tabName === activeTab}">
<span class="tab-copy">{{ tabName }}</span>
<span class="tab-background">
</span>
</button>
</li>
</ul>
</nav>
</header>
<article>
<div class="container">
<transition name="fade" mode="out-in" appear :duration="500">
<tab-content v-for="(tabContent, t) in tabs" :data="tabContent" :key="'content'+t" v-if="t === activeTab" inline-template>
<div class="content-wrapper">
<div class="recipes" v-for="(recipe, i) in data.recipes" :key="i">
<a v-bind:href="recipe.url" class="recipe-card__card-link"></a>
<img :src="recipe.image" alt="" class="recipe-card__image">
<div class="recipe-card__text-wrapper">
<h2 class="recipe-card__title">{{recipe.name}}</h2>
<div class="recipe-card__details-wrapper">
<p class="recipe-card__excerpt">{{recipe.body}}</p>
<a v-bind:href="recipe.url" class="recipe-card__read-more">Read more <i class="fa fa-arrow-right"></i></a>
</div>
</div>
</div>
</div>
</tab-content>
</transition>
</div>
</article>
</main>
I tried to combine instances search and tab into just one instance tab, but it always gives me a Vue warning:
[Vue warn]: Property or method "searchQuery" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
Also, I feel like I can have just the wrong approach to this problem I am trying to solve. Please, any suggestions are welcome. I am stuck.
vue.js
how can I make it look all in one line, next to each other?
TEMPLATE:
<div class="product">
<button #click="removeFromCart" :disabled="!inStock"> −</button>
<span>
<p v-if= "inStock == 0"> 💔 <span :class="{isRed: inStock === 0}"> {{inStock}} </span> </p>
<p v-else> ♥ {{inStock}}</p>
<button #click="addToCart" > + </button>
</span>
</div>
You can use class="row" for example in your div. Than all buttons, p-tags and so one will be shown on a row - like this:
<div class="row">
<!-- YOUR CODE IN HERE -->
</div>
To define the width of your b-button, p-tags, etc. you can use class="col-md-5 for example.. here is a link how you can define the width of a element in vue.js.
URL: https://vuetifyjs.com/en/components/grids/#order-first-and-last
Hopefully this helps you out.
I'm using vue-slick-carousel to build a slider. I have an issue with image which I wrapped as a link. When I click on image redirect doesn't happen. Also I have a title under image which I wrapped as a link too, and with text it works great, but when I click on image it doesn't. It doesn't work only on mobile devices, on desktop when I click on image it makes redirect.
Here is my code:
<VueSlickCarousel
ref="slick"
v-bind="slickOptions"
class="post-category__slider"
>
<div
v-for="post in posts"
:key="`post-${post.id}`"
class="post-category__list-item"
>
<div class="row">
<div class="col-lg-6">
<div
class="post-category__list-item-image mb-4"
>
<a
:href="`/${item.slug}/${post.slug}`"
>
<img
:src="$store.state.env.panelUrl + post.get_thumbnail"
:alt="post.title"
>
</a>
</div>
</div>
<div class="col-lg-6">
<div class="d-lg-flex flex-lg-wrap flex-lg-column justify-content-lg-between h-100">
<div class="mb-4">
<h4 class="post-card__text-block-title">
<a :href="`/${item.slug}/${post.slug}`">
{{ post.title }}
</a>
</h4>
<div>
{{ post.short_story }}
</div>
</div>
</div>
</div>
</div>
</div>
</VueSlickCarousel>
Try adding pointer-events: none to the images. It should do the trick.
please share your properties for a better picture, also try adding only the property with its object something like this: :href="item.slug/post.slug", but for better reference provide your properties.
I have the following object with a "multimedia" array:
I only need one of the urls, but no idea how ot get it
<div
class="card mb-3"
style="max-width: 540px;"
v-bind:key="news.artices"
v-for="news in newsList" >
<div class="row no-gutters">
<div class="col-md-8">
<div class="card-body">
//this doesn't work
<p v-for="image in news.multimedia" v-bind:key="image">
{{image[0].url}}
</p>
//this works, but shows all
<p v-for="image in news.multimedia" v-bind:key="image">
{{image.url}}
</p>
<h5 class="card-title">{{news.title}}</h5>
</div>
</div>
</div>
</div>
If you want to display only one element of the multimedia array, then you don't need to use v-for unnecessarily. You can simply use:
<p v-bind:key="image" v-if="news.multimedia && news.multimedia.length">
{{ news.multimedia[0].url }}
</p>
Also, you can use v-if to make sure this div is only rendered if news.multimedia has a valid value and it not an empty array.
It looks like multimedia is an array of objects, so you could do: news.multimedia[0].url.
When using BS3 and patterns/designs that are similar to the media object layout:
<div class="media">
<a class="pull-left" href="#">
<img class="media-object" src="..." alt="...">
</a>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
...
</div>
</div>
Does it make more sense to recreate the pattern using BS3 grids (and thus built-in media queries, sorta like thumbnails)? For example:
<div class="row">
<a class="col-sm-5 col-md-4" href="#">
<img src="holder.js/100%x112" alt="media-like-object">
</a>
<div class="col-sm-6 col-md-7">
<h4 class="hidden-xs">Media heading</h4>
...
</div>
</div>
Or is there some way to utilize the built-in media object responsively? I guess I'm confused as the media object seems to be static. What am I missing?