Can :key be used without v-for in VUE? - javascript

I use VUE to animate the slider (a list of images). There are two/three slides, each consisting of maximum 9 images. I have a computed property slide which returns the current set of images. There is another property start which stands for the number of the first image of a current slide. The <ul> element is the direct descendant of <transition>, so the animation takes place only when <ul>'s key changes. The first snippet is how I'd like to solve the problem. It is working but I can't find any information if it's ok to use a :key property on an element without v-for loop.
How was the problem solved untill now? There were two v-for loops. Slide computed property returned [slide] and artificially looped through one-element table. The problem I see is that v-for loops take the whole objects as :key and it's not what documentation recommends. The second snippet is how the code looks right now.
<transition>
<ul :key="this.start">
<li v-for="image in slide" :key="image.id">
<a>
<img />
</a>
</li>
</ul>
</transition>
<!--CURRENTLY-->
<transition>
<ul v-for="slide in slides" :key="slide">
<li v-for="image in slide" :key="image">
<a>
<img />
</a>
</li>
</ul>
</transition>

Since you asked me to post my comment as answer, I will simply quote the documentation: https://v2.vuejs.org/v2/api/#key
It can also be used to force replacement of an element/component
instead of reusing it. This can be useful when you want to:
Properly trigger lifecycle hooks of a component
Trigger transitions
For example:
<transition>
<span :key="text">{{ text }}</span>
</transition>
When text changes, the <span> will always be replaced instead of
patched, so a transition will be triggered.

Related

Vue.js: Use aria-controls with conditional rendering in vue.js

I have two buttons which toggle some additional information on screen.
I added the buttons the aria-controls attribute und I render an id for the infobox.
Now I still get an error, when I validate the html, because I show this infobox only if a variable in the vuex store is true.
I render it with v-if.
So that means if the button was not clicked the element is not in the DOM and therefore the corresponding id is missing and I get an error.
I tried to use v-show because this would only hide it.
But this would still only render one infobox instead of 2.
Is the only way to get this right to make two infoboxes in the template and add the v-show to both? Or is there a nicer way to use aria-controls.
Thanks for any help
Best
m
Edit:
These are my buttons which have aria-controls.
<template>
<div>
<ul v-if="nav.items">
<li
v-for="(item, key) in nav.items"
#keyup.esc="closeInfoBox">
<button to="" aria-controls="item.name" aria-expanded="false">Designathon</button>
</li>
</ul>
</div>
</template>
And this is my infobox component:
<template>
<div class="Infobox" v-if="infoboxOpen" id="//should correspond to aria controls">
<span v-html="infoContent">Some content</span>
</div>
</template>
Which is only shown if infoboxOpen === true (from vuex store) and the content is replaced depending on which of the buttons is pressed.
(I left out some of this stuff, to make the code easier to understand and to focus on my question here).
This is where I could replace the v-if with the v-show but that would still render only one content. And I would like to have it as dynamic as possible, because users can add more infoboxes in the backend...
Hope this helps understanding my issue.
You're almost there, just make aria-controls a dynamic attribute using
:aria-controls="infoboxOpen ? item.name : ''":
<template>
<div>
<ul v-if="nav.items">
<li
v-for="(item, key) in nav.items"
#keyup.esc="closeInfoBox">
<button to="" :aria-controls="infoboxOpen ? item.name : ''" aria-expanded="false">Designathon</button>
</li>
</ul>
</div>
</template>

Problems using angular ng-style, not updating in IE

I've created a simple directive in Angular which generates a scroller to display some products.
I'm having an issue with one part of the code.
<ul ng-style="{'margin-left':{{currentMargin}}+'px'}">
<li ng-repeat="tyre in tyres" ng-style="{'width':{{liWidth}}+'px'}">
<div class="imageContainer"><img src="../Images/eutl/{{tyre.image}}"/></div>
<div class="details">
<h3>{{tyre.name}}</h3>
About this tire
</div>
</li>
</ul>
and this is what it looks like in the browser once executed
<ul ng-style="{'margin-left':0+'px'}">
<!-- ngRepeat: tyre in tyres -->
<li ng-repeat="tyre in tyres" ng-style="{'width':265+'px'}" class="ng-scope" style="width: 265px;">
<div class="imageContainer"><img src="../Images/eutl/tire.jpg"></div>
<div class="details">
<h3 class="ng-binding">Fuel Efficient</h3>
About this tire
</div>
</li>
<!-- end ngRepeat: tyre in tyres --></ul>
after executing this on my page I get the scroller and the ng-style inside the "li" elements gets displayed correctly, while the ng-style for the "ul" doesn't.
I've tried multiple solutions, even trying to add the same exact ng-style from the "li" element and it just doesn't get processed and no style is added.
Can anyone help me by pointing out a mistake in my markup or a possible cause for one ng-style working on the Li elements and the other not working on the UL itself?
The other problem I'm having is that the value of the currentMargin is not updating in IE8/9 and so on.
Thanks
ng-style accepts an Angular expression that evaluates to an object. This means that if you want to use a variable inside that expression, you can use it directly (without the double-curlies):
ng-style="{width: liWidth + 'px'}"
Double-curlies are used when you want to insert a dynamic, interpolated value to an argument that accepts a string, like <img alt="{{product.name}} logo">. You then put an expression inside those brackets.
Try to do :
ng-style="{'width':liWidth+'px'}">
No curly bracket, a lot of ng directive don't like it

How to trigger a custom animation and wait for it to complete before and after data bind

I am rendering markup which contains wrapping divs every 5 items
<div class="snap" ng-repeat="itemsChunk in items">
<a class="timeline-item" href="#" ng-repeat="item in casestudyChunk">
<img class="img-responsive" src="{{item.ImageUrl}}" />
</a>
</div>
Where item is an array split into chunks. Split array into chunks
Since the markup needs completely re-rendering after the datasource has changed, I can't use the normal animate hooks. I instead want to fade out all the items before the change, and fade the newly rendered markup in.
How can I do this with Angular?
Update
An option I've got is to apply a fadeOut class to the elements, listen for the complete event and then bind afterwards. This doesn't feel like the proper angular way of doing it though. Is there a better way?
Also I am lazy loading images, so need to run a function to trigger this after binding. I have seen this done with a timeout, again if there is a better way I am interested.
You can try use animate.css and add to your
<div class="snap" ng-repeat="itemsChunk in items">
fadeIn css-class
<div class="snap animated fadeIn" ng-repeat="itemsChunk in items">
there you can find simmilar solution

Using slick to create a carousel from li elements

I'm using slick to create a carousel from list items
The structure of list is like this
<div class="slicker">
<li>
<img />
</li>
<li>
<img />
</li>
<li>
<img />
</li>
</div>
I'm unable to create a carousel of it .
The content rather appears as a normal list.
When checking the node I see the relevant classed added to the dom.
Link for slick :https://kenwheeler.github.io/slick/
Actually, Slick use div element as slide by default, but you can change it with the "slide" parameter (slide | element | 'div' | Element query to use as slide).
In your case you need to have (in your js) something like:
$('.slicker').slick({
slide: 'li'
});
You can also change your code with 'div' like "v2solutions.com" said but this change your semantics.
Could you please try <div> instead of <li>. slick seems to be working with <div> only.

Positioning issue in ExpressionEngine cms

I have a positioning issue with my in expression engine. click Here On the following link I am looping elements with <div id="services-container"> I have noticed it loops fine on the first row however begins to misalign on the second row. I have made attempts to use the switch="" tag to create an individual class for each loop, see below:
{exp:channel:entries channel="services" dynamic="no" sort="asc|desc"}
<div id="services-container" class="{switch='1|2|3|4|5|6'}">
<div class="service-content">
<img src="{service_image}" alt="banner" alt="{alt}" class="service-banner">
<p>{service_head_line}</p>
{service_listed_items}
<ul class="service-credentials">
<li>{service_list_1}</li>
<li>{service_list_2}</li>
<li>{service_list_3}</li>
</ul>
<ul class="service-credentials">
<li>{service_list_4}</li>
<li>{service_list_5}</li>
<li>{service_list_6}</li>
</ul>
View related projects ยป
{/service_listed_items}
</div><!--service-content-->
</div><!--SERVICES CONTAINER-->
{/exp:channel:entries}
When i try to class these classes out in my style sheet nothing is happening. Does anyone know what i am doing wrong?
This involves ExpressionEngine but also css. Basically you are trying to create a grid with 3 items in each row, correct ?
Each of these "row" has to adopt a float containment strategy, since it only contains 3 floated items. The way I would go about it using the switch parameter:
{exp:channel:entries channel="services" dynamic="no" orderby="date" sort="asc"}
{if "{switch='one|two|three'}" == "one"}<div class="row">{/if}
<div class="item">
...code...
</div>
{if "{switch='one|two|three'}" == "three" || count == total_results}</div>{/if}
{/exp:channel:entries}
That code would include a div with a class of row every three items in that loop.
Then, if your items are floated, your rows must have some sort of float clearing strategy to contain them like overflow:hidden; or a clearfix method.

Categories