Accessibility on vue.js app - Show div when click Tab Key - javascript

I will create a menu with jump marks for accessibility that is only visible when the tab key on the keyboard is clicked.
How can I implement this in Vuetify? is there a way to use something like #click for this?
This is my html code for the menu:
<template>
<div class="m-block-tab-jump-sections" data-module="tab-jump-sections" v-on:click.tab="onClick">
<div class="jump-sections js-sections h-break-in">
<a href="#tab-jump-section--metamenu" class="jump-link" title="" target="" tabindex="50">
zur Top-Navigation
</a>
</div>
</div>
</template>

In order to capture the tab on the entire page, you may need to look at putting the following on the app element:
v-on:keydown.tab='handleTab'
Now you can open a menu or do other actions in the handler.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
showMenu: false,
clickcount: 0,
items: [
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me 2' },
],
}),
methods: {
handleTab(event) {
this.showMenu = true;
}
}
})
<div id="app" v-on:keydown.tab='handleTab'>
<v-app id="inspire">
<div class="text-center">
<v-menu offset-y v-model='showMenu'>
<template v-slot:activator="{ on }">
<v-btn
color="primary"
dark
v-on:focus='handleTab'
>
Dropdown
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(item, index) in items"
:key="index"
#click=""
>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
<v-text-field></v-text-field>
<v-text-field></v-text-field>
<v-text-field></v-text-field>
<v-text-field></v-text-field>
</v-app>
</div>
Here is a sample:

Related

VueJs - I don't understand how I could pass a Boolean value to a chid component

I know that the subject was certainly treated somewhere, but I really don't understand how I could pass a variable to a child component.
What I'm trying to do, is passing 'displayTogglingMenu' in the parent component to 'toggle' in the child.
Parent component
data(){
return {
selectedItem: 1,
displayTogglingMenu: false,
items: [
{ text: 'Home', name: 'home', icon: 'mdi-home' },
{ text: 'Courses', name: 'courses_index', icon: 'mdi-school' },
{ text: 'Enrolments', name: 'enrolments_index', icon: 'mdi-format-list-bulleted' },
{ text: 'Lecturers', name: 'lecturers_index', icon: 'mdi-account-tie' },
],
}
},
Child Component
data(){
return {
toggle: valueOfParentComponent,
alertMessage: '',
loadTable: true,
courses: [],
expendable: [],
...
},
Here is the component I'm trying to hide, as asked by Tim:
<div class="table-container">
<b class="circle"></b>
<v-app>
<v-content>
<v-card>
<v-card-title>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
class="search"
></v-text-field>
<v-spacer></v-spacer>
<router-link :to="{ name: 'new_course'}" class="newItem">New course</router-link>
</v-card-title>
<v-data-table
:headers="courseHeaders"
:items="courses"
:items-per-page="10"
:loading="loadTable"
loading-text="Loading... Please wait"
:search="search"
:single-expand="singleExpand"
:expanded.sync="expanded"
item-key="id"
show-expand
class="elevation-1"
>
<template v-slot:item.title="{ item }">
<transition-group name="list" tag="p">
<span class=" list-item" v-bind:key="item">{{item.title}}</span>
</transition-group>
</template>
<template v-slot:item.actions="{ item }">
<transition-group name="list" tag="p">
<span class=" list-item" v-bind:key="item">
<router-link :to="{ name: 'edit_course', params: { id: item.id } }" class="edit-btn" title="Edit">
<v-icon med>mdi-pencil</v-icon>
</router-link>
<v-btn v-on:click="deleteCourse(item.id)" class="del-btn " title="Delete" >
<v-icon med>mdi-delete</v-icon>
</v-btn>
</span>
</transition-group>
</template>
<template v-slot:expanded-item="{ headers, item }" >
<td :colspan="headers.length" class="item-description" >
<h4 >Course description:</h4>
<p >{{ item.description }}</p>
</td>
</template>
</v-data-table>
</v-card>
</v-content>
</v-app>
<b class="circle2"></b>
</div>
Parent
<template>
<Component :toggle="displayTogglingMenu" />
</template>
<script lang='ts'>
import Component from 'Componenet.vue'
import { defineComponent } from 'vue';
export default defineComponent({
components: {Component},
data() {
return {
displayTogglingMenu: false
}
}
});
</script>
Child
<template>
<div v-show="toggle"></div>
</template>
<script lang='ts'>
import { defineComponent } from 'vue';
export default defineComponent({
props: ['toggle']
});
</script>
The value of displayTogglingMenu in parent will be availible as toggle in the child
You might need to get the value as this.$props.toggle depending on the context
You could pass data from parent to child components using properties. Here are the docs
Eg.
<child-componenet :prop-name="parent value that could also be reactive"></child-component>
Props are reactive so your child-component will react to any change on its properties, you could use the property in a v-if or v-show

Change checkbox icon when checked Vuejs Vuetify

So I am trying to check the checkbox Icon to something more custom, perhaps a different icon, however, I tried a couple different things like pseudo elements with no success. right now what this does is loops through data and displays the name and when checked highlights it based on the css class. What I am trying to do is when check change the checkbox icon.
css
.unchecked{
color: gray;
}
.checked{
background-color: #ffff00;
}
Vuejs Component.
Vue.component('check-list', {
template: `
<v-container>
<v-row >
<v-col >
<v-checkbox
v-for="item in values"
:key="item.id"
:value="item.id"
v-model="selected"
>
<template v-slot:label>
<div :class="selected.includes(item.id) ? 'checked' : 'unchecked'">
{{item.name}}
</div>
</template>
</v-checkbox>
</v-col>
</v-row>
<pre>{{selected}}</pre>
</v-container>
`,
data: function () {
return {
selected: [],
values: [
{id:'1',name:'Name 1'},
{id:'2', name:'Name 2'},
{id:'3', name:'Name 3'},
],
ex4: ['red']
}
},
methods: {
},
})
new Vue({
el: '#components-demo',
vuetify: new Vuetify({
icons: {
iconfont: 'md',
},
}),
data: () => ({
}),
})
#chewie, it is possible to change the checkbox icon in Vuetify, There is a specia prop to handle this
:on-icon="'icon-name'"
:off-icon="'icon-name'"
Please find the full code below
<div id="app">
<v-app id="inspire">
<v-container
class="px-0"
fluid
>
<v-row >
<v-col >
<v-checkbox
:on-icon="'mdi-heart'"
:off-icon="'mdi-home'"
v-for="item in values"
:key="item.id"
:value="item.id"
v-model="selected"
>
<template v-slot:label>
<div :class="selected.includes(item.id) ? 'checked' : 'unchecked'">
{{item.name}}
</div>
</template>
</v-checkbox>
</v-col>
</v-row>
<pre>{{selected}}</pre>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
selected: [],
values: [
{id:'1',name:'Name 1'},
{id:'2', name:'Name 2'},
{id:'3', name:'Name 3'},
],
ex4: ['red']
}
},
})
Please find the working codepen here:
https://codepen.io/chansv/pen/QWdEPvB?editors=1010

Vuetify Item group how to preselect item?

I am trying to preselect item from vuetify item-group. It works for string but not for objects. In the vuetify document, they have used string array as the item list for the item-group. It works fine.
If I try to use an object array as the item list it doesn't work
<div id="app">
<v-app id="inspire">
<v-card class="mx-auto" max-width="500">
<v-list shaped>
<v-list-item-group v-model="model" multiple>
<template v-for="(item, i) in items">
<v-divider
v-if="!item"
:key="`divider-${i}`"
></v-divider>
<v-list-item
v-else
:key="`item-${i}`"
:value="item"
active-class="deep-purple--text text--accent-4"
>
<template v-slot:default="{ active, toggle }">
<v-list-item-content>
<v-list-item-title v-text="item.name"></v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-checkbox
:input-value="active"
:true-value="item"
color="deep-purple accent-4"
#click="toggle"
></v-checkbox>
</v-list-item-action>
</template>
</v-list-item>
</template>
</v-list-item-group>
</v-list>
</v-card>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{ name: "Connect"}
],
model: [{name: "Connect"}]
}),
})
You can implement using unique value from your data, it can be a id or something else. You need to pass you unique value inside of your model in form of Array and then the same unique value should be configure with your <v-list-item>.
Please check code snippet and working Codepen demo.
Code snippet:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [],
model: [1, 3, 6]
}),
methods: {
getValue(item) {
return `${item.id}. - ${item.title.toLocaleUpperCase()}`;
}
},
created: function() {
let self = this;
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => self.$data.items = json)
}
});
<div id="app">
<v-app id="inspire">
<v-card class="mx-auto" max-width="100%">
<v-list shaped>
<v-toolbar color="indigo" dark>
<v-toolbar-title>List posts :- jsonplaceholder</v-toolbar-title>
</v-toolbar> <br/>
<v-list-item-group v-model="model" multiple>
<template v-for="(item, i) in items">
<v-divider
v-if="!item"
:key="`divider-${i}`"
></v-divider>
<v-list-item
v-else
:key="`item-${i}`"
:value="item.id"
active-class="deep-purple--text text--accent-4"
>
<template v-slot:default="{ active, toggle }" >
<v-list-item-content>
<v-list-item-title v-text="getValue(item)"></v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-checkbox
:input-value="active"
:true-value="item.id"
color="deep-purple accent-4"
#click="toggle"
></v-checkbox>
</v-list-item-action>
</template>
</v-list-item>
</template>
</v-list-item-group>
</v-list>
</v-card>
</v-app>
</div>

Controlling visibility of multiple sibling identical components from the same parent while keeping isolated scope

Using Vue and Vuetify Data Tables I built a table in which each row presents an item of an array of objects.
Each row had a button which triggered a dialog which presented a form in which you could edit each row's data.
Here's the problem with instructions: https://codepen.io/gkatsanos-the-bold/pen/VwZzKeq
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
gateways: [],
dialog: false,
form: {
title: ""
}
}),
mounted() {
this.getGateways().then(data => {
this.gateways = data;
});
},
methods: {
async getGateways() {
const response = await fetch(
"https://jsonplaceholder.typicode.com/posts"
);
const data = response.json();
return data;
},
openDialog(item) {
setTimeout(() => {
this.dialog = true;
this.form.title = this.item.title
});
}
}
});
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-content>
<v-container>
<v-data-table :items="gateways">
<template #item="{ item }">
<tr>
<td>{{ item.id }}</td>
<td>{{ item.title }}</td>
<td>
<v-menu>
<template #activator="{ on }">
<v-btn small class="meter-point-options-menu action-column-item" v-on="on">
open menu
</v-btn>
</template>
<v-list>
<v-list-item>
<v-btn color="red lighten-2" dark #click="openDialog()">
Click Me
</v-btn>
<v-dialog v-model="dialog" width="500">
<v-card>
<v-card-title>
ID: {{ item.id }}
</v-card-title>
<v-card-title>
TEXT: {{ item.title }}
</v-card-title>
<v-card-text>
<br> Issues:
<ol>
<li>Every time you close and open a Dialog / Popup, all of the previous ones open together because they're still in the DOM.</li>
<li>Notice that after navigating the pages, some of the ID and texts shown in the modal dialogs are different from the item opened!</li>
<v-form ref=form>
</v-form>
</v-card-text>
<v-card-actions>
<div class="flex-grow-1"></div>
<v-btn color="primary" text #click="dialog = false">
close this
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-list-item>
</v-list>
</v-menu>
</td>
</tr>
</template>
</v-data-table>
</v-container>
</v-content>
</v-app>
</div>
As you see opening one dialog opens all the previous ones.
How should I tackle the issue of controlling the visibility of the v-dialogs in a unique fashion? I am thinking of moving them outside of the loop and having only one v-dialog and not one for every row of the table.

Vue updates all button text after changing specific button

Hi everyone I'm playing around with Vue JS but for some how I cannot get what I expected. Below are my code.
Template
<div id="app">
<v-app id="inspire">
<div class="text-xs-center" v-for="x in count" :key="x">
<v-menu offset-y>
<v-btn
slot="activator"
color="primary"
dark
>
{{name}}
</v-btn>
<v-list>
<v-list-tile
v-for="(item, index) in items"
:key="index"
#click="test(item.title)"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-app>
</div>
Vue
new Vue({
el: '#app',
data: () => ({
name: 'default',
items: [
{ title: 'Click Me 1' },
{ title: 'Click Me 2' },
{ title: 'Click Me 3' },
{ title: 'Click Me 2' }
],
count: 10
}),
methods: {
test(title) {
this.name = title
}
}
})
What I want is that when I change a specific button text the other buttons should not be affected. But it seems my code is doing the opposite. What am I missing here? Any help, explanation would be much appreciated. Thanks
new Vue({
el: '#app',
data: () => ({
name: 'default',
items: [
{ title: 'Click Me 1' },
{ title: 'Click Me 2' },
{ title: 'Click Me 3' },
{ title: 'Click Me 2' }
],
count: 10
}),
methods: {
test(title) {
this.name = title
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.3/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.3/dist/vuetify.min.css">
<div id="app">
<v-app id="inspire">
<div class="text-xs-center" v-for="x in count" :key="x">
<v-menu offset-y>
<v-btn
slot="activator"
color="primary"
dark
>
{{name}}
</v-btn>
<v-list>
<v-list-tile
v-for="(item, index) in items"
:key="index"
#click="test(item.title)"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-app>
</div>
You are iterating over a normal number, in your example 10, so you are just showing 10 times the same variable name.
If you now change that variable name to something, it will change in all the buttons accordingly.
You need some way to save the different names, e.g. an array of objects like your items with all the titles.
I took your code and changed it a bit. Instead of iterating over a fixed count, I created an array of names and iterate over that array. When you click one of the buttons and change the text, instead of just changing the universal name attribute - you change the name at the position in the array.
new Vue({
el: '#app',
data: () => ({
names: [
{name: 'default 1'}, {name: 'default 2'}, {name: 'default 3'}, {name: 'default 4'}],
items: [
{ title: 'Click Me 1' },
{ title: 'Click Me 2' },
{ title: 'Click Me 3' },
{ title: 'Click Me 4' }
],
}),
methods: {
test(title, index) {
this.names[index].name = title
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.5.3/vuetify.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.5.3/vuetify.css.map">
<div id="app">
<v-app id="inspire">
<div class="text-xs-center" v-for="(x, index) in names" :key="'name' + index">
<v-menu offset-y>
<v-btn
slot="activator"
color="primary"
dark
>
{{x.name}}
</v-btn>
<v-list>
<v-list-tile
v-for="(item, i) in items"
:key="'item' + i"
#click="test(item.title, index)"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-app>
</div>

Categories

Resources