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>
Related
Currently trying figure out how to make use of Alpine to simplify the management of a list. most of it is fine, but can't seem to get the value for show and showAll to make it to the items on the list.
<div x-data="{ show:false, showAll:false }">
#foreach($items as $item) <!-- laravel blade bit -->
<div x-data="{ active:{{ $item->foo }} }" x-show="show && (active || (!active && showAll))">
<div>stuff</div>
</div>
#endforeach
<button #click="show = ! show">btn1</button>
<button #click="showAll = ! showAll">btn2</button>
</div>
So basically the active variable is fine, despite there being a lot of them, but show and showAll from the parent don't seem to count.
To note, the x-datas aren't direct parent child as shown here, there's stuff in between. And secondly I haven't been able to check if it's okay to have a conditional in x-show, might just have made a mistake there.
In
https://codesandbox.io/s/vskdf
I have a template that is not rendered inside of my vuedraggable. Any ideas why?
InventorySectionGroup.vue:
<template>
<!-- this div renders -->
<div class="inventory-section-group">
<p>{{ itemSectionGroupProps.itemSectionCategoryName }}</p>
<div
v-for="group in itemSectionGroupProps.itemSectionCategoryItemList"
:key="group.itemSectionCategoryId"
>
<inventory-section-group-item :itemDataProps="group">
</inventory-section-group-item>
</div>
<!-- div doesn't render :-(
<draggable v-model="itemSectionGroupProps.itemSectionCategoryItemList">
<transition-group>
<div
v-for="group in itemSectionGroupProps.itemSectionCategoryItemList"
:key="group.itemSectionCategoryId"
>
<inventory-section-group-item :itemDataProps="group">
</inventory-section-group-item>
</div>
</transition-group>
</draggable> -->
</div>
</template>
Fixed errors related to comp. init:
https://codesandbox.io/s/y2cur?file=/src/components/InventorySectionDraggable.vue
Nested dnd can be replicated like:
https://codesandbox.io/s/priceless-perlman-n6psw?file=/src/components/MyContainer.vue
You have several errors in your code (browser console + ESlint), try fixing them, this will highlight several issues that may be blocking at some point.
As for your current issue, you do have some duplicated code: the block that is rendered and the one that is not. This is coming from the fact that the :key needs to be unique. Since your code is the same on the 2 blocks, the key is duplicated and only one is rendered I guess.
If you take the second block with it's
<div :key="group.itemSectionCategoryId">
And update it to some naive unique key like this
<div :key="`${group.itemSectionCategoryId + 1}`">
This will render the 2 blocks as expected I guess.
Here is the end result.
I've decided to go with nested draggable (build satellite data related to inventory groups and items):
https://codesandbox.io/s/x8ur4?file=/src/components/InventorySectionDraggable.vue
I still need to wrap the props around components.
Done:
https://codesandbox.io/s/rmh2n
I am trying to implement a functionality which will toggle a Vuetify badge element for each array object within the list when the containing div has been hovered over.
I am able to create a hover like functionality within v-for array list using css, which is fairly simple but how can I achieve similar outcome using vuetify components? As I have not found any questions discussing this or demonstrating it, assume it is possible. Have looked into
First Link
Second Link
Second Link
And much more but have not found similar enough example of what I desire.
I have added codepen example of what I currently have.
The badge should only appear on the element which is currently being hovered, however all badge elements are being executed when any element has been hovered on.
CodePen Link
Maybe I have missed out something obvious
HTML Part
<template>
<div id="app">
<div>My favourite fruit is <b>{{favouriteFruit}}</b></div> <br>
<div v-for="(dataArray, index) in testArray" #click="setCurrent(dataArray.name)">
<v-badge
:color="computedFavFruitColor[index]"
right
v-model="show"
>
<template v-slot:badge>
<span><v-icon color="#ECF0FF">{{computedFavFruit[index]}}</v-icon></span>
</template>
<div #mouseover="show = true" #mouseleave="show = false">
{{dataArray.name}}
</div>
</v-badge>
</div>
</div>
</template>
Any further help of suggestions regarding this manner would be appreciated.
While the show property is global, it counts for every item you hover. You want to target the element you hover. So I suggest to keep track of the index of the item you hover like this: https://codepen.io/reijnemans/pen/JjPrayp?editors=1010
<div v-for="(dataArray, index) in testArray" #click="setCurrent(dataArray.name)">
<v-badge
:color="computedFavFruitColor[index]"
right
>
<template v-slot:badge>
<span v-if="show == index"><v-icon color="#ECF0FF">{{computedFavFruit[index]}}</v-icon></span>
</template>
<div #mouseenter="show = index" #mouseleave="show = null">
{{dataArray.name}}
</div>
</v-badge>
</div>
And show = null ipv show = true in data block of vue
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.
I have just been taking a look at some example code on the Vue JS documentation about transitions. I am trying to add buttons to each list item and give them the ability to toggle content within each list.
Here is an example of my instance:
<ul id="demo">
<li>
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</li>
<li>
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</li>
</ul>
new Vue({
el: '#demo',
data: {
show: true
}
})
How can I programatically allow my two <li> tags to have their own buttons that only shows the content within itself?
I know I could just add another data object called show2 and amend the button to <button v-on:click="show2 = !show2"> however this is a manual process that I don't want to have to do ever time a new <li> is added.
How can I programatically achieve this within Vue?
Thanks
You should create another component, let's call Togglable. You can pass the content with props or using slots as shown on the docs here
With the new component you can use it for each li. Check v-for as well if your data is dynamic too.
It is going to look similar to this:
<togglable content="hello" button-name="Toggle"></togglable>