Vue-i18n and v-select - can't translate - vue.js

I have a problem to translate the information with vue i18n in my v-select. All others translation work but not this one... And i don't find a solution ...
HTML :
<v-card-text>
<v-select v-model="model" :items="propsList" :items-text="propsList.text" label="Select a reason:" clearable />
</v-card-text>
DATA eg : ($t = i18n)
propsList: [
{ text: this.$t('XXX.A') as string, value: 'X' },
{ text: this.$t('XXX.B') as string, value: 'Y' },
{ text: this.$t('XXX.C') as string, value: 'Z' },
],
Traduction :
{ "en": {
"XXX" : {
"A": "A", ...}},
"fr": {
"XXX" : {
"A": "A", ...}},
In my App.vue :
data ... :
languages: [
{ text: 'English', value: 'en' },
{ text: 'Français', value: 'fr' },
],
watch: {
language(val: string) {
this.setLanguage(val);
this.$i18n.locale = val;
},
},
I'm keep trying ! But thanks by advance :)

There is a prop called :get-option-label that is useful for i18n, that way you can just pass the i18n key in your option array:
<v-select :options="options" :get-option-label="option => $t(option.text)"></v-select>
Then options would look like this:
options = [
{ text: "XXX.A", value: 0 }
{ text: "XXX.B", value: 1 }
{ text: "XXX.C", value: 3 }
]
More details: https://vue-select.org/api/props.html#getoptionlabel

v-select doesn't have a prop named 'items-text' (items with s). You probably mean item-text (without s).
the prop item-text is used to specify the "path" where each item of your data has the text, it defaults to the string "text" which means the text of the item is found at the property "text"
if for example, you have the item with the structure:
{
value: 'some value',
name: 'John'
}
You should pass the string "name".
since you have your data with the text as text property, your template should look like this:
<v-card-text>
<v-select v-model="model" :items="propsList" label="Select a reason:" clearable />
</v-card-text>
Other options for this prop are:
An array of strings
Use this for nested properties, say for example you have your item's structure as follows:
{
value: 'whatever',
data: {
name: {
en: 'John'
}
}
}
you should pass ['data', 'name', 'en'], Vuetify will resolve the name.
A callback function
The callback function you pass will be called for each item and the item itself will be passed as a parameter, you should return whatever string you want to be displayed, this might be useful if you want to concatenate two properties of your items, e.g. first name and last name. or to display a prefix based on some value

Related

Are there any possible ways to search multiple attribute in v-autocomplete in Vuetify?

I have an array of objects bind to item prop of v-autocomplete.
this is my data:
products: [
{
text: "Apple",
value: 209
},
{
text: "Banana",
value: 229
}
]
<v-autocomplete>
...
:item="products"
:search-input.sync="search"
</v-autocomplete>
so, i want to have the ability to search by both 'text' and 'value'. Currently, i am able to search only one among them.
Use custom filter function to v-autocomplete as follows
<v-autocomplete>
...
:filter="customFilter"
:item="products"
:search-input.sync="search"
</v-autocomplete>
methods: {
customFilter (item, queryText, itemText) {
// return true or false according to your logic
// i.e queryText matches with item object
},
},
Yes, you can search multiple attribute using filter attribute which is provide in the docs:
customSearch(item, queryText, itemText) {
const data = item.text.toLowerCase() + item.value.toLowerCase()
const searchText = queryText.toLowerCase()
return textOne.indexOf(searchText) > -1
}
and use in the template like this:
<v-autocomplete
spellcheck="false"
:filter="customSearch"
...
</v-autocomplete>
Refer this docs: https://vuetifyjs.com/en/api/v-autocomplete/#props

How to remove preselected tag in vue-multiselect

I need a dropdown that supports tagging and can be styled easily, so I decided to implement vue-multiselect. It works but the problem is that I have a predefined tag in my dropdown when the page loads and I don't what that, how can I remove it? Here is how it looks now:
and here is how I want it to look:
Here is my html code:
<div>
<multiselect v-model="value" tag-placeholder="Add this as new tag" placeholder="Assesors" label="name" track-by="code" :options="options" :multiple="true" :taggable="true" #tag="addTag"></multiselect>
</div>
and here is my js:
data () {
return {
showAddUserDialog: false,
value: [
{ name: 'Assesors', code: 'as' }
],
options: [
{ name: 'Assesors', code: 'as' },
{ name: 'Finance', code: 'fi' },
{ name: 'Sales', code: 'sa' }
]
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
}
Well, by the <multiselect> configuration you used and the expected behavior your showed...
You have this https://imgur.com/a/D9nEKfD to become this https://imgur.com/a/baTYXht
I looks like you want to load your page only showing the placeholder, but if you'd like to only show your placeholder, you shouldn't have a value in the value variable, as you have:
data () {
return {
showAddUserDialog: false,
value: [
{ name: 'Assesors', code: 'as' } // <- remove this
],
options: [
{ name: 'Assesors', code: 'as' },
{ name: 'Finance', code: 'fi' },
{ name: 'Sales', code: 'sa' }
]
}
}
Because the behavior of the component is show your current tags, right?
So if this tag is the placeholder, you can add it to the value when the user submits the form without choosing any other tag.
But if you want to have it there as the value and trickery the component to only show it as a placeholder, I suggest you to deep dive in the docs about custom templating...
Here talks about it https://vue-multiselect.js.org/#sub-custom-option-template
And here talks about the tags slots
https://vue-multiselect.js.org/#sub-slots
Here is an example:

How to set a default value in <v-select>?

I have this select here:
<v-select px-4 class='select'
v-model="form.accountType"
:items="accountTypes"
:label="$t('form.accountType')"
:rules="[rules.required, rules.validAccountType]"
color= 'primary'
></v-select>
I want the select initialice with one of the items of the select:
accountTypes () {
const types = [
{
value: 'business',
text: this.$t('form.accountTypeBusiness')
},
{
value: 'personal',
text: this.$t('form.accountTypePersonal')
}
]
return types
}
I've passed a with this prop:
form: {
accountType: 'Personal'
}
but the v-model doesn't work. Is there any way to set Personal as a default value?
Value is case sensitive so start it with a small letter since the value in array is starts with small letter.
form: {
accountType: 'personal'
// -----------^--------
}

Vue.js. Render of different kinds of child components according to a list of conditions

I'm new to not OOP, and VUE.JS especially.
I have a list of conditions, according to them I should show on the page several different kinds of components.
How can I render, for example, 2 TextInput components (or 3.. 10) dynamically and read the entered text in parent after clicking a button?
Thank you in advance.
You didn't provide any code, so I'm not sure what exactly you are trying to do.
If you want to display multiple components, just use v-for and specify conditions in v-if, which will detemine whether this particular component will be rendered:
<input
v-for="input in inputs"
v-if="input.show"
v-model="input.model"
:placeholder="input.label"
type="text"
>
<button #click="handleButtonClick()">Button text</button>
data: () => ({
inputs: [
{
label: 'input 1',
model: '',
show: true
},
{
label: 'input 2',
model: '',
show: true
}
]
}),
methods: {
handleButtonClick () {
console.log(this.inputs)
}
}
If you don't know the type of component you need to display you can use dynamic components.
In a nutshell this defers the type of component used at runtime based on a value.
Let's assume you have 2 different type of components
TextComponent
ImageComponent
You can have a list of items
data () {
return {
items: [
{
id: 1,
val: 'something',
type: 'TextComponent'
},
{
id: 2,
val: 'something',
type: 'ImageComponent'
}
]
}
}
Now you can iterate over the list and display the component based on type
<component v-for="item in items" :key="item.id" :is="item.type" v-model="item.value />
If type is not the exact name of the component, you can translate it inside the :is condition. Something like this.
:is="getComponentFromTag(item.type)"
And then write the conversion method
methods: {
getComponentFromTag (tag) {
switch (tag) {
case 'text':
return 'TextComponent'
case 'img':
return 'ImageComponent'
}
}
}
For the example above I'm assuming that items look like this:
items: [
{
id: 1,
val: 'something',
type: 'text'
},
{
id: 2,
val: 'something',
type: 'img'
}
]

Bootstrap-vue: how can I display the text of a selected item?

I am using Bootstrap Vue to render a select input. Everything is working great - I'm able to get the value and change the UI based on the option that was selected.
I am trying to change the headline text on my page - to be the text of the selected option. I am using an array of objects to render the options in my select input.
Here is what I'm using for my template:
<b-form-group
id="mySelect"
description="Make a choice."
label="Choose an option"
label-for="mySelect">
<b-form-select id="mySelect"
#change="handleChange($event)"
v-model="form.option"
:options="options"/>
</b-form-group>
Here is what my data/options look like that I'm passing to the template:
...
data: () => ({
form: {
option: '',
}
options: [
{text: 'Select', value: null},
{
text: 'Option One',
value: 'optionOne',
foo: {...}
},
{
text: 'Option Two',
value: 'optionTwo',
foo: {...}
},
}),
methods: {
handleChange: (event) => {
console.log('handleChange called');
console.log('event: ', event); // optionOne or optionTwo
},
},
...
I can get optionOne or optionTwo, what I'd like to get is Option One or Option Two (the text value) instead of the value value. Is there a way to do that without creating an additional array or something to map the selected option? I've also tried binding to the actual options object, but haven't had much luck yet that route either. Thank you for any suggestions!
Solution
Thanks to #Vuco, here's what I ended up with. Bootstrap Vue passes all of the select options in via :options. I was struggling to see how to access the complete object that was selected; not just the value.
Template:
<h1>{{ selectedOption }}</h1>
<b-form-group
id="mySelect"
description="Make a choice."
label="Choose an option"
label-for="mySelect">
<b-form-select id="mySelect"
v-model="form.option"
:options="options"/>
</b-form-group>
JS:
...
computed: {
selectedOption: function() {
const report = this.options.find(option => option.value === this.form.option);
return option.text; // Option One
},
methods: {
//
}
...
Now, when I select something the text value shows on my template.
I don't know Vue bootstrap select and its events and logic, but you can create a simple computed property that returns the info by the current form.option value :
let app = new Vue({
el: "#app",
data: {
form: {
option: null,
},
options: [{
text: 'Select',
value: null
},
{
text: 'Option One',
value: 'optionOne'
},
{
text: 'Option Two',
value: 'optionTwo'
}
]
},
computed: {
currentValue() {
return this.options.find(option => option.value === this.form.option)
}
}
});
<div id="app">
<b-form-group id="mySelect" description="Make a choice." label="Choose an option" label-for="mySelect">
<b-form-select id="mySelect" v-model="form.option" :options="options" />
</b-form-group>
<p>{{ currentValue.text }}</p>
</div>
Here's a working fiddle.
You have an error in your dictionary.
Text is showed as an option.
Value is what receive your variable when option is selected.
Is unneccesary to use computed property in this case.
let app = new Vue({
el: "#app",
data: {
form: {
option: null,
},
options: [{
value: null,
text: 'Select'
},
{
value: 'Option One',
text: 'Option One'
},
{
value: 'Option Two',
text: 'Option Two'
}
]
}
});
Fiddle with corrections
Documentation