how to select a default value in q-select from quasar? - vue.js

I need my q-select to select the "name" depending on the previously assigned "id".
Currently the input shows me the "id" in number and not the name to which it belongs.
<q-select
class="text-uppercase"
v-model="model"
outlined
dense
use-input
input-debounce="0"
label="Marcas"
:options="options"
option-label="name"
option-value="id"
emit-value
map-options
#filter="filterFn"
#update:model-value="test()"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> No results </q-item-section>
</q-item>
</template>
</q-select>
Example I would like the name that has the id: 12 to be shown loaded in the q-select.
const model = ref(12);
const options = ref([]);
const filterFn = (val, update) => {
if (val === "") {
update(() => {
options.value = tableData.value;
});
return;
}
update(() => {
const needle = val.toLowerCase();
options.value = tableData.value.filter((v) =>
v.name.toLowerCase().includes(needle)
);
});
};

I'm running into the same issue and couldn't find a proper way to set default value of object type.
I ended up use find() to look for the default value in the options and assign it on page created event.
created() {
this.model = this.options.find(
(o) => o.value == this.model
);
}

Related

v-rating not displaying the value stored in the firestore database

need a bit of help here. I want to create a contractor's performance rating where we can rate the contractor using vuetify v-rating and save it into firebase firestore.
I succeeded to update rating and save it in firestore but whenever I refresh the page it shows an empty rating slots like this rating slot is empty after refresh, not showing the rating that i've just key-in even though it is stored in firestore.
it does show up if I want it to display as a number, like this: it shows the rating value if display it as a number.
How to display it in the form of star rating itself?
<template>
<div>
<v-data-table
dense
:headers="headers"
:items="subwork"
:loading="loading"
class="elevation-1"
style="margin: 3%;">
<template v-slot:[`item.rating`]="{ item }">
<v-rating
color="yellow"
half-increments
#input="giveRating(item, $event)"
item-value="rating"></v-rating>
</template>
<template v-slot:no-data>
<v-btn color="primary" #click="initialize"> Reset </v-btn>
</template>
</v-data-table>
</div>
</template>
To load the document & add the rating to firestore
methods: {
initialize() {
this.loading = true
this.subwork = []
firestore
.collection('registersubwork')
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
this.subwork.push({ ...doc.data(), id: doc.id, })
this.loading = false
})
console.log(this.subwork)
})
},
giveRating(item, value) {
this.editedIndex = this.subwork.indexOf(item);
this.editedItem = Object.assign({}, item);
console.log(item, value)
if (this.editedIndex > -1) {
Object.assign(this.subwork[this.editedIndex], this.editedItem);
} else {
this.subwork.push(this.editedItem);
}
var data = {
rating: this.editedItem.rating,
};
firestore
.collection("registersubwork")
.doc(this.editedItem.id)
.set({ rating: value }, { merge: true })// .update(data)
.then(() => {
console.log("Rating updated succesfully!");
})
.catch(e => {
console.log(e);
});
},
},
Thanks!
You're using item-value="rating". as far as i know it's value="5" and for binding it should be :value="item.rating" try changing this. if you don't have rating with each item make sure to check that.

Fill vuetify combobox with data from function

I have a Vuetiy combobox that's part of a form in which the user can search voor data by email and it returns a object (a visitor):
<EmailInput
v-model="selectedVisitor"
:required="true"
:autocomplete="true"
:items="visitors"
/>
<template>
<div>
<v-text-field
v-if="!autocomplete"
:rules="[
(v) => !!v || $t('error.emailRequired'),
(v) => /.+#.+\..+/.test(v) || $t('error.emailInvalid'),
]"
outlined
:label="label"
required
#input="$emit('input', $event)"
/>
<v-combobox
v-if="autocomplete"
:rules="[
(v) => !!v || $t('error.emailRequired'),
]"
:label="label"
outlined
append-icon="arrow_drop_down"
:items="items"
item-text="email"
item-value="email"
#input="$emit('input', $event)"
>
<template v-slot:selection="data">
{{ data.item.email || data.item }}
</template>
<template v-slot:item="data">
{{ data.item.name }} - {{ data.item.email }}
</template>
</v-combobox>
</div>
</template>
<script>
export default {
props: {
required: Boolean,
items: Array,
autocomplete: Boolean,
},
computed: {
label() {
if (this.required === true) {
return this.$i18n.t('labels.emailReq');
}
return this.$i18n.t('labels.email');
},
},
};
</script>
If an existing visitor is found, the other form fields are filled, otherwise just the email is sent to the newVisitor object.
selectedVisitor(val) {
if (typeof val === 'object' && val !== null) {
this.newAppointment.visitorId = val.id;
this.existingVisitor = true; // we don't have to write it to the db
Object.assign(this.newVisitor, val); // for displaying the data only, object assign because db array was edited too when data was modified or deleted
} else if (val === null || val === '') {
this.newAppointment.visitorId = '';
this.newVisitor = {};
} else {
this.newVisitor.email = val;
}
},
The user then clicks a button and the data gets sent to the multipleVisitors array.
The problem is with the function that repopulates these form fields if the user wants to edit the data:
editVisitor(email) {
// get the visitor that needs to be edited
const visitorArray = this.multipleVisitors.filter((el) => el.email === email);
const visitor = visitorArray[0];
// set the visitor to the form
this.newVisitor = visitor;
// variable set to combobox
this.selectedVisitor = visitor.email;
// remove the visitor from the visitor array
this.multipleVisitors = this.multipleVisitors.filter((el) => el.email !== email);
},
The form is filled in except for the combobox which stays empty. If I look at vue dev tools the variable assigned to the v-model does contain the email address.
I've tried assigning the whole object to selectedVisitor but that does not change anything.
this could maybe help
<v-combobox :items="MyFillFuntion()"></v-combobox>
<v-combobox :items="MyFillFuntion(scopeData)" # optional></v-combobox>
and don't forget
<script>
export default {
data: () => ({
MyFillFuntion() {
let array_i_need_to_fill = [];
// your process ... ...
// and finally
return array_i_need_to_fill;
}
}),
props: {
required: Boolean,
items: Array,
autocomplete: Boolean,
},
computed: {
label() {
if (this.required === true) {
return this.$i18n.t('labels.emailReq');
}
return this.$i18n.t('labels.email');
},
},
};
</script>

How to check v-radio on the edit screen?

I am practicing the code example below.
I applied Vuetify.
This is the edit screen showing the data fetched from the API.
The problem is that the selected v-radio is not checked.
What is the problem?
<v-radio-group v-model="designType" :mandatory="false" row>
<v-radio
v-for="n in 3"
:key="n"
:label="`Type ${n}`"
:value="n"
:checked="n === designType"
:aria-checked="n === designType"
/>
{{designType}} //<<----- test value is no problem
</v-radio-group>
...
// script
data() => ({
...
designType: 1,
...
}),
mounted() {
this.edit = true
this.formEdit()
,
methods: {
async formEdit() {
const apiUrl = 'http://127.0.0.1:3100/cards/'
await this.$axios.get(apiUrl + this.$route.params.id).then(res => {
this.designType = res.data.designType
})
}
}

Quasar custom input component field validation

I am trying to create Quasar custom select component with autocomplete. Everything works fine except the validation error, the validation error is showing only when I click the input box and leave without adding any value. But, the form is submitting even there are any errors.
Component code
<q-select
ref="members"
v-model="sModel"
use-input
:options="filteredOptions"
:multiple="multiple"
:use-chips="useChips"
:label="label"
:option-label="optionLabel"
:option-value="optionValue"
#filter="filterFn"
#input="handleInput"
emit-value
map-options
hint
dense
outlined
lazy-rules
:rules="rules"
>
<template v-slot:prepend>
<q-icon :name="icon" />
</template>
</q-select>
</template>
<script>
export default {
props: {
value: Array,
rules: Array,
icon: String,
label: String,
optionValue: String,
optionLabel: String,
options: Array,
multiple: Boolean,
useChips: Boolean
},
data () {
return {
filteredOptions: this.options,
sModel: this.value,
validationErrors:{
}
}
},
methods: {
filterFn (val, update) {
if (val === '') {
update(() => {
this.filteredOptions = this.options
// with Quasar v1.7.4+
// here you have access to "ref" which
// is the Vue reference of the QSelect
})
return
}
update(() => {
const needle = val.toLowerCase()
const optionLabel = this.optionLabel
this.filteredOptions = this.options.filter(function(v){
// optionLabel
return v[optionLabel].toLowerCase().indexOf(needle) > -1
})
})
},
handleInput (e) {
this.$emit('input', this.sModel)
}
},
}
</script>
In the parent component, this is how I am implementing it,
<AdvancedSelect
ref="members"
v-model="members"
:options="extAuditEmployees"
icon="people_outline"
multiple
use-chips
label="Team Members *"
option-label="formatted_name"
option-value="id"
:rules="[ val => val && val.length && !validationErrors.members > 0 || validationErrors.members ? validationErrors.members : 'Please enter Team members' ]">
</AdvancedSelect>
Try adding this method on select component methods:
validate(...args) {
return this.$refs.members.validate(...args);
}
It worked for me, apparently it sends the validation of the input to the parent
Source consulted: https://github.com/quasarframework/quasar/issues/7305
add ref to the form and try to validate the form.
you can give give props "greedy" to the form.

Vue.js store data as dictionary using v-model

I have
<v-switch
v-model="Books" v-for="option in options"
:value="option.id" :label="option.display_name"
:key="option.id"
:disabled="disabled"
color="primary" dense hoverable>
</v-switch>
and
export default{
name: Books
data: () => ({
Books: []
})
}
I want to store my data as objects where option.id is the key, and inside you have id and presence. If the switch wasn't selected that presence is null
"97":{"id":"97","presence":"1"},
"98":{"id":"98","presence":"1"},
"99":{"id":"99","presence":null},
How would I do that ?
You can do that with Array.prototype.reduce.
const arrayToObject = (array, keyField) =>
array.reduce((obj, item) => {
obj[item[keyField]] = item
return obj
}, {})
const convertedBooks = arrayToObject(books, "id")
This is a common problem, and there a lot of articles that guide you on how to convert an array to a dictionary, for example here is one