Using item-text as a function to customize Vietify v-combobox items - vuejs2

I'd like to customize my combobox items, to as using item-text prop as described here:
https://vuetifyjs.com/en/components/combobox
Here is a fork of a vuetify example where I define a function whick always returns 'test':
:item-text="() => 'test'"
Codepen : https://codepen.io/anon/pen/yWxQdN?editors=1010
Is there a reason why my function is not called?

For your Codepen example, instead of the item-text property, use the selection scoped slot.
<v-combobox :items="items">
<template slot="selection" slot-scope="{item, index}">
{{ yourFunc() }}
</template>
</v-combobox>

As said in documentation, "item-text" seems to be used only if items are objects, and not if they are primitives.
When using objects, will look for a text and value field. This can be
changed using the item-text and item-value props

Related

How can we use v-for and v-if in the same element?

I am building a component in which I have to iterate over each action and check conditions on each action. So, how can I use v-for and v-if in the same element?
The Vue.js Style Guide recommends against this:
Never use v-if on the same element as v-for.
There are two common cases where this can be tempting:
To filter items in a list (e.g. v-for="user in users" v-if="user.isActive"). In these cases, replace users with a new computed property that returns your filtered list (e.g. activeUsers).
To avoid rendering a list if it should be hidden (e.g. v-for="user in users" v-if="shouldShowUsers"). In these cases, move the v-if to a container element (e.g. ul, ol).
Your best option is to use a <template> tag for your v-for and apply your v-if inside that on whichever HTML tag you're using. For an instance:
<template v-for="(user, index) in users">
<div v-if="user.isActive" :key="index">
// your HTML code here
</div>
</template>
or use a computed value as mentioned in the docs. For example, something like this:
computed: {
activeUsers() {
return this.users.filter(user => user.isActive)
}
}
Without seeing an example of your current code, I could only guess how you might adapt the above to suit your individual needs.

Display translation on a component in Vuejs

I want to show a translation on the title of a component.
Here is the HTML code:
<user-card
:totalUser="totalUsers"
color="primary"
icon="UserIcon"
user-title="Total users"
/>
On my user-card component I have this:
<b-card class="text-center">
<b-avatar
:variant="`light-${color}`"
class="mb-1"
size="45"
>
<feather-icon
:icon="icon"
size="21"
/>
</b-avatar>
<div class="truncate">
<h2 class="mb-25 font-weight-bolder">
{{ totalUser}}
</h2>
<span>{{ user-title }}</span>
</div>
</b-card>
And to use translation I have this syntax where I get the translated terms from the JSON file:
{{$t("Total users")}}
How can I implement this on the user-title?
Have a look at this, I have tried to replicate your scenario in code sandbox.
sample app
What you are doing wrong is that $t is a function that accepts variable name which has an actual message in it, first you have to define a variable e.g totalUserTitle: 'Total users' for multiple languages like I did in index.js, and then you can use it as $t(totalUserTitle).
Just use v-bind and pass the expression to your user-card component directly:
<user-card
...
:user-title="$t('Total users')"
/>
You're actually already using this syntax in multiple places, this directive just tells Vue to "dynamically bind one or more attributes, or a component prop to an expression", which is exactly what you're looking for here.
This will evaluate $t('Total users') as an expression and then pass the result to your component as a prop.

When to use prop modifier in vue?

When to use prop modifier in vue?
In vue document,I find the prop modifier in v-bind here: https://v2.vuejs.org/v2/api/#v-bind
my question is this:
https://v2.vuejs.org/v2/api/#v-bind
From the docs:
Modifiers:
.prop - Bind as a DOM property instead of an attribute (what’s the difference?). If the tag is a component then .prop will set the property on the component’s $el.
This is useful, because some HTML inputs can't receive a value as attribute, but need to be passed on the ref itself.
See for example the indeterminate state of a checkbox. Normally you'd need to do
<template>
<!-- this doesn't work, because there's no indeterminate prop on the checkbox, it only exists on the DOM element -->
<input type="checkbox" :indeterminate="indeterminateProp" />
</template>
<script>
beforeUpdate() {
//set indeterminate directly on the dom element object
// this is what you'd always have to do if v-bind.prop didn't exist
this.$refs.myCheckbox.indeterminate = this.indeterminateProp;
}
</script>
and keep track of it manually outside of vue's reactivity system.
But thanks to .prop, you can just do
<input type="checkbox" :indeterminate.prop="indeterminateProp"/>
Without having to play with lifecycle hooks.
So .prop basically tells vue "apply this value on the DOM node itself (the one you'd normally get from $refs) instead of trying to apply it as an attribute or property"
You can use this modifier to pass a property to a component.
<myComponent v-bind:<PropName></myComponend> is the same as <myComponent :<PropName>></myComponend>
Checkout this link here: https://v2.vuejs.org/v2/guide/components-props.html.

Why do not undeclared props pass to the components's root element?

I made a wrapper around Vuetify's 'v-dialog' component named 'Modal' and wanna pass props through it:
<template>
<v-dialog
class="modal"
max-width="600"
v-on="vDialogListeners"
>
<v-card>
<v-card-title class="headline">
<slot></slot>
</v-card-title>
<v-card>
...
</v-dialog>
</template>
I use it like this ('value' prop):
<Modal
:value="showModal"
:confirm="true"
#close="onModalClose"
#click:outside="onModalClose(false)">
Are you sure you'd like to log out?
</Modal>
I know about $attrs and it works if I bind it explicitly, i.e, v-bind="$attrs" within <v-dialog> opening tag.
My question: why doesn't work it by default, that's without explicit v-bind="$attrs", if <v-dialog> is the component's root element and should accept all props undeclared in the component, or I'm wrong and misunderstand this part of documentation?
I used to think that v-bind="$attrs" is only used in case inheritAttrs: false in order to pass udeclared props to a component's not-root element (a nested one).
I have a guess: maybe, it only concerns the components root html element (e.g., input tag) by default.
It seems I figured out the proper usage of it. By default, it adds these $attrs to the DOM element as attributes. By explicit binding, I can pass them to the necessary child component. By setting inheritAttrs = false, I cancel the default behavior of adding attributes to the DOM element. Thus, I can combine these options to get the suitable behavior.

v-on:change does not work for vue-multiselect

I am using vue-multiselect component in my vue.js project, I am using v-on directive to execute a function on the change event ,
<multiselect v-model="selected" :options="projects" :searchable="false" :custom-label="customLabel" track-by="name" v-on:change="executeLoader">
<template slot="customLabel" slot-scope="{ customLabel }"><strong>{{ option.name }}</strong></template>
</multiselect>
I have example full code here: https://codesandbox.io/s/yjjon0vzxj
the v-on:change was working with <select> component but it stopped workigng with vue-multiselect ! I tried with v-on:click="executeLoader" but that too didnt worked either..
#click will not trigger the method executeLoader with vue multiselect. You can use #input - which is similar to v-on:change, #close, #select as in example below:
<multiselect placeholder="Pick at least one"
select-label="Enter doesn’t work here!"
:value="value"
:options="options"
:multiple="true"
:searchable="true"
:allow-empty="false"
:hide-selected="true"
:max-height="150"
:max="3"
:disabled="isDisabled"
:block-keys="['Tab', 'Enter']"
#input="onChange"
#close="onTouch"
#select="onSelect">
</multiselect>
In your case I would try #input="executeLoader"
In vue-multiselect, since it is a component you can't treat it to behave like a simple <select> element.
In components, when you expect them to behave and "listen" to click events just like other html tag, then you should add an event modifier called: .native.
So, you can do on any component:
<... #click.native="executeLoader" />
But that is not what you are looking for I think. You want to trigger a function when you add more and more tags, or in short: when the selected items increase.
for that, vue-multiselect exposes the #input event, so you can handle using:
<... #input="executeLoader" />
And now just call executeLoader and accept the arguments as:
methods: {
executeLoader(selectedItems) {}
}