I have 3 desks in a table having role_id 2, 4 and 6. I have two tables. I want to display a different role name on a button based on the current user's role_id.
I want to display:
the role name having role_id 4 if the current user_role_id = 2
the role name having role_id 6 if the current user_role_id = 4.
user table
registration table
code
<span v-if="user.user_role_id ==results.desk_user_role_id">
<v-btn small color="primary" v-on:click="getNextDesk" style="width:400px;">Forward to </v-btn>
<v-btn small color="primary" v-on:click="getPreviousDesk" style="width:400px;">Revert </v-btn>
</span>
Script code
getNextDesk(currentdeskid) {
if (currentdeskid === 2) {
return 'Technical Desk';
}
if (currentdeskid === 4) {
return 'Executive Desk';
}
return '';
},
getPreviousDesk(currentdeskid) {
if (currentdeskid === 6) {
return 'Technical Desk';
}
if (currentdeskid === 4) {
return 'Registration Desk';
}
return '';
},
This is my best guess about what you're trying to do:
new Vue({
el: "#app",
data() {
return {
user: { user_role_id: 2 },
roles: {
2: { name: 'Registration', next: 4 },
4: { name: 'Technical', next: 6, previous: 2 },
6: { name: 'Executive', previous: 4 }
}
}
},
computed: {
forwardTo() {
const { next } = this.roles[this.user.user_role_id];
return next ? 'Forward to ' + this.roles[next].name : false;
},
revertTo() {
const { previous } = this.roles[this.user.user_role_id];
return previous ? 'Revert to ' + this.roles[previous].name : false;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
User:
<select v-model="user.user_role_id">
<option v-for="(role, id) in roles" :value="id">{{ role.name }}</option>
</select>
</div><br />
<button v-show="forwardTo">{{ forwardTo }}</button>
<button v-show="revertTo">{{ revertTo }}</button>
</div>
Related
I have a component that uses Multiselect from #vueform/multiselect. The problem is when the user selects an option and the tag is created, if enter is pressed it will deselect that option. How am I able to control that? I tried adding #keydown.enter.prevent="deselect" but it doesn't work.
Here is how my component looks:
<template>
<Multiselect
v-model="propValue"
:options="this.options"
:placeholder=this.$filters.translate(this.placeholder)
:closeOnSelect="false"
:searchable="this.searchable"
:noResultsText="$filters.translate(this.labels.noResult)"
ref="multiselect"
#change="change"
#click="click"
#deselect="remove"
:mode="this.mode"
:hideSelected='false'
:max="this.limit">
<template v-slot:caret>
<img class="caretMultiselect" :src="filterIcon" alt="Filter">
</template>
<template v-slot:beforelist v-if="showWarning">
<span class="beforeListContainer">
<p class="beforeListWarningMessage">{{this.warningMessage}}</p>
</span>
</template>
</Multiselect>
</template>
<script>
import Multiselect from '#vueform/multiselect';
import filter from '#/assets/filter.svg';
import { nextTick } from 'vue';
export default {
components: {
Multiselect,
},
props: {
disabled: Boolean,
placeholder: String,
mode: {
type: String,
default: 'single'
},
showWarning: {
type: Boolean,
default: false
},
options: Object,
value: Array,
warningMessage: String,
limit: Number
},
emits: ['change', 'reachedMax', 'removedTag'],
data(){
return {
filterIcon: filter,
labels: {
noResult: 'No matching records'
},
propValue : this.value,
searchable: true
}
},
methods: {
change(value) {
this.propValue = value;
this.$emit('change', value);
if (this.propValue.length == this.limit) {
nextTick(() => {
this.$refs["multiselect"].close();
})
return;
}
this.searchable = true;
},
click(val) {
if (this.propValue.length == this.limit) {
this.searchable = false;
for (let idx in this.options) {
if (this.options[idx].label == val.target.ariaLabel && !this.propValue.includes(this.options[idx].value)) {
this.$emit('reachedMax');
}
}
}
},
remove() {
this.$emit('removedTag');
}
},
watch: {
options(current) {
if (current.length !== 0) {
for (let idx in this.propValue) {
let option = this.propValue[idx];
if (!current.some(e => e.value === option)) {
let index = this.propValue.indexOf(option);
index > -1 ? this.propValue.splice(index, 1) : '';
this.$emit('change', this.propValue);
}
}
}
}
}
}
</script>
Thanks in advance, appreciate the help.
I have a vuetify v-btn-toggle like this:
<v-btn-toggle
v-model="toggle_values"
dense
multiple
>
<v-btn value="A">
A
</v-btn>
<v-btn value="B">
B
</v-btn>
<v-btn value="C">
C
</v-btn>
</v-btn-toggle>
But the binding v-model is an array. How could I trigger individual toggled event for buttons A, B, C like this:
data() {
return { toggle_values: [] }
},
computed: {
stateA: {
get() {
// get A value from other place
},
set(isPressed) {
// do something on A value changed
}
},
stateB: {
get() {
},
set(isPressed) {
}
},
stateC: {
get() {
},
set(isPressed) {
}
},
}
We have to create one method to read the state of buttons and other to set the state, all operations take place in the toggle_values.
data() {
return { toggle_values: [] }
},
methods: {
getToggleStateIsPressed: function (value) {
return this.toggle_values.indexOf(value) === -1 ? false : true;
},
setToggleState: function (value, press) {
if (press && this.toggle_values.indexOf(value) === -1) {
this.toggle_values.push(value);
} else if (!press) {
this.toggle_values = this.toggle_values.filter((val) => {
return val != value;
});
}
},
},
computed: {
stateA: {
get() {
return this.getToggleStateIsPressed("A");
},
set(isPressed) {
this.setToggleState("A", isPressed);
},
},
stateB: {
get() {
return this.getToggleStateIsPressed("B");
},
set(isPressed) {
this.setToggleState("B", isPressed);
},
},
stateC: {
get() {
return this.getToggleStateIsPressed("C");
},
set(isPressed) {
this.setToggleState("C", isPressed);
},
},
},
If you want to play with the values and see they changing, add this:
Model: {{ toggle_values }} <br />
A is pressed {{ getToggleStateIsPressed("A") }}<br />
B is pressed {{ getToggleStateIsPressed("B") }}<br />
C is pressed {{ getToggleStateIsPressed("C") }}<br />
<v-btn #click="stateA = !stateA">{{ getToggleStateIsPressed("A")?'unpress':'press' }} A</v-btn>
<v-btn #click="stateB = !stateB">{{ getToggleStateIsPressed("B")?'unpress':'press' }} B</v-btn>
<v-btn #click="stateC = !stateC">{{ getToggleStateIsPressed("C")?'unpress':'press' }} C</v-btn>
Hope it helps! ;)
I am trying to make a drop down "select" field disabled under certain conditions in my app.
I have successfully done this with buttons already using a prop (disableBtn) that i pass up from the root of my app to the button component I made.
I try to do the EXACT same thing on a select component and it refuses to pass the prop (disableOption) back into the child component, even though its passing back many other binded props that work fine and build the options out in the drop down correctly.
I am logging the values on screen right now and can see they are updating in the main app component, but its not passing that back to the child for some reason.
Where am I off here? My understanding is you store the values you want to change in data() in the app.vue, then create a prop for them in the child component and bind them in the HTML. This has been working fine in all my other use cases.
app.vue
<template>
<div class="container">
<img alt="logo" src="./assets/logo.png">
<Header title="Provider Manager" :custTZ="custTZ" :shippingState="shippingState" :patientID="patientID" :custName="custFullName" :custEmail="custEmail" :custPhone="custPhone" />
<div v-if="providerVisibility" class="providerInfo">
<Button #btn-click="providerPicked" id="first-avail" text="First Available" />
<br />
<Select #dd-select="providerPickedSelect" :disabled="disableOption" :selectName="selectName" :id="id" :eligibleProviders="eligibleProviders" :labelFor="labelFor" :labelText="labelText" />
{{ disableOption }}
</div>
<div v-if="providerSelected" >
<hr>
<br />
<h2>Provider: {{ chosenProvider }} </h2>
<br />
</div>
<div v-if="providerSelected" >
<BookingSlots #selectSlot="removeUnselected" :slots="slots" />
<br />
<Button #btn-click="bookMeeting" text="Confirm Request" />
</div>
</div>
</template>
<script>
import { ZOHO } from "./assets/ZohoEmbededAppSDK.min.js";
import Header from './components/Header'
import Button from './components/Button'
import BookingSlots from './components/BookingSlots'
import Select from './components/Select'
const axios = require('axios');
export default {
name: 'App',
components: {
Header,
Button,
BookingSlots,
Select
},
data() {
return{
slots: [],
providerVisibility: true,
providerSelected: false,
currentProvider: 'None Assigned',
chosenProvider: '',
custFullName: '',
custEmail: '',
custPhone: '',
shippingState: '',
patientID: '',
custTZ: '',
providerZID: '',
eligibleProviders: [],
disableBtn: false,
disableOption: true,
}
},
methods: {
removeUnselected(id) {
console.log('id', id)
this.slots = this.slots.filter((slot) => slot.id === id)
},
providerPicked(id) {
console.log("id" + id)
console.log("currentProvider",this.currentProvider)
//Toggle front end visibility
this.providerSelected = true;
this.providerVisibility = false;
if(id === "first-avail"){
// hit booking engine, get name of first available
console.log("FIRST AVAIL")
this.chosenProvider = "Need to Hit Booking App";
}
if(id === "current-provider"){
// hit zoho values and get contact assigned provider
console.log("CURRENT PROVIDER")
this.chosenProvider = this.currentProvider;
}
},
providerPickedSelect(id, selectValue) {
if(this.id === "provider-select"){
// Get values from our DB for the provider selected
console.log("Provider-Select")
this.providerSelected = true;
this.providerVisibility = false;
this.chosenProvider = selectValue;
}
},
bookMeeting() {
//Book the meeting
console.log("book meeting called")
}
},
created() {
//Hit zoho and get customer info back
ZOHO.embeddedApp.on("PageLoad",(data) =>
{
console.log(data);
//Custom Business logic goes here
let entity = data.Entity;
let recordID = data.EntityId[0];
ZOHO.CRM.API.getRecord({Entity:entity,RecordID:recordID})
.then((data) => {
console.log(data.data[0])
// Set values scraped from CRM Contact profile
if(data.data[0].provider !== null && data.data[0].provider !== "None Assigned" ){
this.currentProvider = data.data[0].provider.name;
this.providerZID = data.data[0].provider.id;
}else{
//need to disable button if no doc assigned
this.disableBtn = true;
}
this.custEmail = data.data[0].Email;
this.custFullName = data.data[0].Full_Name;
this.custPhone = data.data[0].Phone;
this.patientID = data.data[0].Patient_ID;
this.shippingState = data.data[0].Mailing_State;
this.custTZ = data.data[0].GTM;
// getEligibleProviders(this.shippingState);
var data = JSON.stringify({
"state":this.shippingState,
});
axios(config)
.then((res) => {
console.log(res.data)
//this.eligibleProviders = res.data;
if(this.eligibleProviders && !this.eligibleProviders.length){
console.log("empty array")
this.eligibleProviders = [{
first_name: "None Avilable in Svc. State",
last_name: ""
}
];
this.disableOption = true;
}else{
console.log("full array")
}
console.log(this.eligibleProviders)
})
.catch((e) => {
console.log(e);
});
});
});
ZOHO.embeddedApp.init();
this.slots = [
{
id: 1,
text: 'Time Slot 1',
providerFname: 'James',
providerLname: "Appleton"
},
{
id: 2,
text: 'Time Slot 2',
providerFname: 'James',
providerLname: "Johnson"
}
];
this.selectName = "provider-select";
this.id = "provider-select";
this.labelFor = "provider-select";
this.labelText = "Choose a Provider: ";
}
}
</script>
select.vue
<template>
<br />
<label :for="labelFor">{{ labelText }} {{ disableOption }}</label>
<select v-on:change="onSelect($event, id)" class="select" :name="selectName" :id="id" :disabled="disableOption" >
<option :value="'none'" selected disabled hidden >Select One</option>
<option :key="provider.id" v-for="provider in eligibleProviders" :value="provider.first_name + ' ' + provider.last_name" >{{ provider.first_name +" "+ provider.last_name }}</option>
</select>
<br /><br />
</template>
<script>
export default {
name: 'Select',
props: {
selectValue: String,
selectName: String,
id: String,
labelFor: String,
labelText: String,
eligibleProviders: Array,
disableOption: Boolean,
},
methods: {
onSelect($event, id) {
console.log($event.target.value)
this.$emit('dd-select', id, $event.target.value);
}
},
emits: ['dd-select']
}
</script>
button.vue
<template>
<button #click="onClick(id)" class="btn" :id="id" :disabled="disableBtn" >{{ text }}</button>
</template>
<script>
export default {
name: 'Button',
props: {
text: String,
id: String,
disableBtn: Boolean,
},
methods: {
onClick(id) {
this.$emit('btn-click', id);
}
}
}
</script>
in select.vue, the props says it wants "disableOption", but you're passing disabled="disableOption"
so you can try updating app.vue with:
<Select
#dd-select="providerPickedSelect"
:disable-option="disableOption"
:select-name="selectName"
:id="id"
:eligible-providers="eligibleProviders"
:label-for="labelFor"
:label-text="labelText"
/>
I'm working with BootstrapVue. I have a b-button in my template where I want to switch its text after clicking on it.
I'm passing my generated unique item.id to my script, but this is not working out in the case that every b-button text will be changed and not only the one I'm clicking. What is the problem in here?
You should be able to copy, paste the code and it should work out.
Please notice that it's just a replica of my code shortened on needed code, so the code should not be changed this much.
My template:
<div v-for="item in inputs" :key="item.id">
<b-button #click="changeText(item)">{{btnText}}</b-button>
</div>
<b-button #click="addInput">Add Input</b-button>
My script:
data() {
return {
collapsed: [true],
id: null,
inputs: [{id: 0}],
btnText: "It's false",
}
},
methods: {
changeText(item) {
this.collapsed[item.id] = !this.collapsed[item.id]
if(this.collapsed[item.id] === true) {
this.btnText = "It's true"
}
else if(this.collapsed[item.id] === false) {
this.btnText = "It's false"
}
},
addInput() {
this.inputs.push({
id: this.id += 1,
})
this.collapsed.push(true);
}
}
Instead of having separate arrays to store the different fields, move them into the inputs[] object array, so that each item in the v-for has its own id, collapsed, and btnText.
Then update changeText() to refer to the fields within the item argument.
Also update the template to use the item.btnText field.
<script>
export default {
data() {
return {
inputs: [{ id: 0, collapsed: true, btnText: `It's true` }], 1️⃣
}
},
methods: {
changeText(item) {
item.collapsed = !item.collapsed 2️⃣
if (item.collapsed) {
item.btnText = `It's true`
} else {
item.btnText = `It's false`
}
},
addInput() {
this.inputs.push({ 1️⃣
id: this.id++,
collapsed: true,
btnText: `It's true`,
})
},
},
}
</script>
<template>
<div>
<div v-for="item in inputs" :key="item.id"> 3️⃣
<b-button #click="changeText(item)">{{ item.btnText }}</b-button>
</div>
<b-button #click="addInput">Add Input</b-button>
</div>
</template>
demo
You can maintain an object for btnText like
data() {
return {
collapsed: [false],
id: null,
inputs: [{id: 0}],
btnText: {0: "It's false"} //Change added
}
},
methods: {
changeText(item) {
this.collapsed[item.id] = !this.collapsed[item.id]
if(this.collapsed[item.id] === true) {
this.btnText[item.id] = "It's true"; //Change added
}
else if(this.collapsed[item.id] === false) {
this.btnText[item.id] = "It's false"; //Change added
}
},
addInput() {
this.inputs.push({
id: this.inputs.length, // Change added
})
this.btnText[this.inputs.length] = 'It's false'; //Change added
this.collapsed.push(true);
}
}
and your template should be like
<div v-for="item in inputs" :key="item.id">
<b-button #click="changeText(item)">{{btnText[item.id]}}</b-button> <!-- Change added -->
</div>
<b-button #click="addInput">Add Input</b-button>
I'm a beginner programmer and I create a spa like trello. Creates boards. In the board creates lists, they are displayed different with different id, but the list items are displayed with the same id and they are duplicated in each list. Sorry for my english:) Help me, please and tell in detail what the problem is.. Thank you very much
vuex file router.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
boards: JSON.parse(localStorage.getItem('boards') || '[]'),
lists: [],
items: []
// items: JSON.parse(localStorage.getItem('items') || '[]')
// lists: JSON.parse(localStorage.getItem('lists') || '[]')
},
mutations: {
addBoard(state, board) {
state.boards.push(board)
localStorage.setItem('boards', JSON.stringify(state.boards))
},
addList(state, list) {
state.lists.push(list)
// localStorage.setItem('lists', JSON.stringify(state.lists))
},
createItemListt(state, item) {
state.items.push(item)
// localStorage.setItem('items', JSON.stringify(state.items))
}
},
actions: {
addBoard({commit}, board) {
commit('addBoard', board)
},
addList({commit}, list) {
commit('addList', list)
},
createItemListt({commit}, item) {
commit('createItemListt', item)
}
},
getters: {
boards: s => s.boards,
taskById: s => id => s.boards.find(t => t.id === id),
lists: d => d.lists,
items: a => a.items
},
modules: {
}
})
the page on which the lists are created MyBoard.vue
<template>
<div>
<div class="wrapper">
<div class="row">
<h1>{{board.title}}</h1>
<div class="list " v-for="list in lists" :key="list.idList">
<div class="list__title">
<h3>{{list.titleList}}</h3>
</div>
<div class="list__card" v-for="item in items" :key="item.idItemList">
<span class="list__item">{{item.itemList}}</span>
<a class="btn-floating btn-tiny btn-check" tag="button">
<i class="material-icons">check</i>
</a>
</div>
<createItemList />
</div>
<createList />
</div>
</div>
</div>
</template>
<script>
export default {
computed: {
board() {
return this.$store.getters.taskById(+this.$route.params.id);
},
lists() {
return this.$store.getters.lists;
},
items() {
return this.$store.getters.items;
}
},
components: {
createList: () => import("../components/createList"),
createItemList: () => import("../components/createItemList")
}
};
</script>
CreateList.Vue
<template>
<div>
<div class="row">
<div class="new-list" v-show="isCreating">
<div class="list__title input-field">
<input
type="text"
required
id="list-title"
class="none validate"
tag="button"
autofocus
v-model="titleList"
v-on:keyup.enter="createList"
/>
<label for="list-title">Enter Title List</label>
</div>
<a class="btn-floating transparent btn-close" tag="button" #click="closeList">
<i class="material-icons">close</i>
</a>
</div>
<div class="create-list z-depth-2" v-show="!isCreating">
<p>Create list</p>
<a
class="btn-floating btn-large waves-effect waves-light deep-purple lighten-2 pulse"
tag="button"
#click="addList"
v-on:keyup.enter="addList"
>
<i class="material-icons">add</i>
</a>
</div>
</div>
</div>
</template>
<script>
export default {
data: () => ({
isCreating: false,
titleList: "",
idList: ""
}),
methods: {
addList() {
this.isCreating = true;
},
closeList() {
this.isCreating = false;
},
createList() {
if (this.titleList == "") {
return false;
}
const list = {
idList: Date.now(),
titleList: this.titleList
};
this.$store.dispatch("addList", list);
this.titleList = "";
this.isCreating = false;
console.log(list.titleList);
}
}
};
</script>
CreateItemList.vue
<template>
<div>
<div class="add-item">
<div class="textarea-item input-field" v-show="isAdding">
<input
type="text"
class="validate"
id="list-item"
v-model="itemList"
v-on:keyup.enter="createItemList"
autofocus
/>
<label for="list-item">Enter Item List</label>
</div>
<a class="waves-effect waves-light btn" v-show="!isAdding" #click="addCard">
<i class="material-icons right">add</i>Add Card
</a>
</div>
</div>
</template>
<script>
export default {
data: () => ({
isAdding: false,
itemList: "",
}),
methods: {
addCard() {
this.isAdding = true;
},
createItemList() {
if (this.itemList == "") {
return false;
}
const item = {
idItemList: Date.now(),
itemList: this.itemList
};
this.$store.dispatch("createItemListt", item);
this.itemList = "";
this.isAdding = false;
}
}
};
</script>
attach photo
Tried to go with the basic idea of the structure you laid out. I added:
id to all items, so they can be identifed
children to appropriate items, so you can keep track of what's in them
const store = new Vuex.Store({
state: {
tables: [
{ id: 1, children: ['1.1', '1.2'] },
{ id: 2, children: ['2.1'] }
],
lists: [
{ id: '1.1', children: ['1.1.1'] },
{ id: '1.2', children: ['1.2.1'] },
{ id: '2.1', children: ['2.1.1', '2.1.2'] },
],
cards: [
{ id: '1.1.1' },
{ id: '1.2.1' },
{ id: '2.1.1' },
{ id: '2.1.2' },
]
},
mutations: {
ADD_CARD(state, listId) {
const list = state.lists.find(e => e.id === listId)
const cards = state.cards
const card = { id: Date.now() }
cards.push( card )
list.children.push( card.id )
},
ADD_LIST(state, tableId) {
const table = state.tables.find(e => e.id === tableId)
const lists = state.lists
const list = { id: Date.now(), children: [] }
lists.push( list )
table.children.push( list.id )
},
ADD_TABLE(state) {
const tables = state.tables
const table = { id: Date.now(), children: [] }
tables.push( table )
},
TRY_MOVING_LIST(state) {
const table1 = state.tables.find(e => e.id === 1)
const table2 = state.tables.find(e => e.id === 2)
const item = table1.children.pop() // remove the last item
table2.children.push(item)
}
},
actions: {
addCard({ commit }, listId) {
commit('ADD_CARD', listId)
},
addList({ commit }, tableId) {
commit('ADD_LIST', tableId)
},
addTable({ commit }) {
commit('ADD_TABLE')
},
tryMovingList({ commit }) {
commit('TRY_MOVING_LIST')
}
},
getters: {
getTables: s => s.tables,
getListById: s => id => s.lists.find(e => e.id === id),
getCardById: s => id => s.cards.find(e => e.id === id),
}
})
Vue.component('CustomCard', {
props: ['card'],
template: `<div>
card ID: {{ card.id }}<br />
</div>`
})
Vue.component('CustomList', {
props: ['list'],
template: `<div>
list ID: {{ list.id }}<br />
<custom-card
v-for="item in list.children"
:key="item"
:card="getCard(item)"
/>
<button #click="addCard">ADD CARD +</button>
<hr />
</div>`,
methods: {
getCard(id) {
return this.$store.getters.getCardById(id)
},
addCard() {
this.$store.dispatch('addCard', this.list.id)
}
}
})
Vue.component('CustomTable', {
props: ['cTable'],
template: `<div>
table ID: {{ cTable.id }}<br />
<custom-list
v-for="item in cTable.children"
:key="item"
:list="getList(item)"
/>
<button #click="addList">ADD LIST +</button>
<hr />
</div>`,
methods: {
getList(id) {
return this.$store.getters.getListById(id)
},
addList(id) {
this.$store.dispatch('addList', this.cTable.id)
}
}
})
new Vue({
el: "#app",
store,
computed: {
tables() {
return this.$store.state.tables
}
},
methods: {
addTable() {
this.$store.dispatch('addTable')
},
tryMovingList() {
// this function will move the last list in table ID 1
// to the end of table ID 2's lists
// NOT FOOLPROOF - you should add error handling logic!
this.$store.dispatch('tryMovingList')
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuex"></script>
<div id="app">
<button #click="tryMovingList()">MOVE LIST</button><br />
<button #click="addTable()">ADD TABLE +</button>
<hr />
<custom-table v-for="item in tables" :key="'table-' + item.id" :c-table="item" />
</div>
With this setup you can change the hierarchy quite easily: just delete an ID from one Array of children and add it to another (e.g. remove '1.1' from table ID 1's children array and add it to table ID 2's children array - everything moved to table ID 2. tryMovingList() does exactly this - this method/action is not foolproof, just for you to try out moving a whole list)
There could be other patterns to solve this problem (like a real linked list data structure or the mediator pattern), but for smaller apps this is OK, I think (I would use it... :) ).
ONE PIECE OF ADVICE
If you want to store state in localStorage on mutations, don't do it by yourself - use Vuex's integrated subscribe mechanism: https://vuex.vuejs.org/api/#subscribe