VUETIFY - How to pass slot to nested select component - vue.js

I'm using last version of vuetify and trying to figure out how to make slots work. Documentation about select may be find here
VSelectWithValidation
<v-select v-model="innerValue" :error-messages="errors" v-bind="$attrs" v-on="$listeners">
<template slot="selection" slot-scope="data">
{{ data.item.name }}
</template>
<template slot="item" slot-scope="data">
{{ data.item.name }} - {{ data.item.description }}
</template>
</v-select>
TestComponent
<VSelectWithValidation
rules="required"
:items="items"
v-model="select"
label="Select">
// I WOULD LIKE SLOTS TO BE AT THIS LEVEL
</VSelectWithValidation>
Basically, I would like the slots to be customized so I need to move them out of the VSelectWithValidation component to be set on the TestComponent
I tried different variations with no success.
https://codesandbox.io/s/veevalidate-components-vuetify-u11fd

VSelectWithValidation
You need to create slot inside your template slot item and bind scope data to able to use from other component ..
<template slot="item" slot-scope="data">
<slot name="item" v-bind="data"></slot>
</template>
TestComponent
You can access that slot by writing v-slot:YourSlotName="hereIsBindData"
<template v-slot:item="data">
{{ data.item.name }} // you can code here whatever you like
</template>

Related

VueJs - Include a button after a v-select

I'm quite a newby using Bootstrap-Vue for a project,
I have a structure like this
<template>
<v-select>
<template slot="option" slot-scope="option">
<div class="d-center">
{{ option.name }}
</div>
</template>
</v-select>
</template>
and I want to put a <b-button></b-button> after the v-select closure, but I get an error, I'm not sure why honestly.
Vuetify has slots to append elements. There are several.
https://vuetifyjs.com/en/api/v-select/#slots
<v-select>
<template #append>
<v-btn>Your Button</v-btn>
</template>
</v-select>

How to specify when a Vue Component has extra functionality?

I have a table component, and this table component has the ability to select attributes, however I only want this ability to be available when I need it to be, aka not every time it's rendered. How do I do this?
Functionality snippet from Component.vue to only be active when in a certain file ie Component2.vue
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<b-table-column field="columnValue" v-slot="props2" class="attr-column">
<b-table :bordered="false" class="attr-table" :striped="true" :data="props2.row.columnValues">
<b-table-column field="columnName" v-slot="itemProps">
<SelectableAttribute :attr-name="props2.row.fieldClass" :attr-id="itemProps.row.id" :model-id="itemProps.row.id" model-name="NewParticipant">
{{ itemProps.row.value }}
</SelectableAttribute>
</b-table-column>
</b-table>
</b-table-column>
</b-table>
Component.vue
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<b-table :striped="striped" :bordered="false" :data="participants" detailed class="participant-table" :row-class="() => 'participant-row'">
<b-table-column field="primaryAlias" :label="t('participant.table.primary_alias')" v-slot="props">
<template v-if="props.row.primaryAlias">
<SelectableAttribute attr-name="Alias" :attr-id="props.row.primaryAlias.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryAlias.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryEmail" :label="t('participant.table.primary_email')" v-slot="props">
<template v-if="props.row.primaryEmail">
<SelectableAttribute attr-name="Email" :attr-id="props.row.primaryEmail.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryEmail.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryAddress" :label="t('participant.table.primary_address')" v-slot="props">
<template v-if="props.row.primaryAddress">
<SelectableAttribute attr-name="Address" :attr-id="props.row.primaryAddress.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryAddress.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>
*<b-table-column field="primaryPhone" :label="t('participant.table.primary_phone')" v-slot="props">
<template v-if="props.row.primaryPhone">
<SelectableAttribute attr-name="Phone" :attr-id="props.row.primaryPhone.id" :model-id="props.row.id" model-name="NewParticipant">
{{ props.row.primaryPhone.value }}
</SelectableAttribute>
</template>
<template v-else>-</template>
</b-table-column>*
<b-table-column v-slot="props" cell-class="cell-action">
<slot v-bind="props.row">
</slot>
</b-table-column>
<template slot="detail" slot-scope="props">
<b-table class="attrs-detail-container" :data="tableDataToDataValueCells(props.row)" cell-class="with-bottom-border">
<b-table-column field="columnName" v-slot="props">
<b>{{ props.row.columnName }}</b>
</b-table-column>
<b-table-column field="columnValue" v-slot="props2" class="attr-column">
<b-table :bordered="false" class="attr-table" :striped="true" :data="props2.row.columnValues">
<b-table-column field="columnName" v-slot="itemProps">
<SelectableAttribute
:attr-name="props2.row.fieldClass"
:attr-id="itemProps.row.id"
:model-id="itemProps.row.id"
model-name="NewParticipant"
>
{{ itemProps.row.value }}
</SelectableAttribute>
</b-table-column>
</b-table>
</b-table-column>
</b-table>
</template>
</b-table>
</template>
You can achieve this by using props that you pass while calling that component. That prop could be anything you need. Here is a small example with simple true/false prop:
// Set the prop in your called component, in this case a boolean
props: {
myBoolean: Boolean
}
// Passing the prop from your parent to the component, where it has to be a property, in this case called myBooleanFromParent
<my-component :myBoolean="myBooleanFromParent"></my-component>
// In your component your template changes according to the passed prop from your parent
<template>
<div>
<div v-if="myBoolean">
If myBoolean is true
</div>
<div v-else>
Else, so if myBoolean is false
</div>
</div>
</template>
This is, as stated, a small and simple example. You can pass any kind of data with props. It could also be a object full of data to handle multiple conditions.

Vuetify: Use v-chip-group inside a v-select selection slot

I am trying to add a v-chip-group in a v-select v-slot=selection but am failing.
Due to design requirements, I have to persist some placeholder text in a multi-select but only have so much width for the component. I want the chips to overflow to the right with a scroll interface like the default v-chip-group but can't seem to work it together.
Goal
Current
How can I get the proxy BaseSelect component, which is basically a wrapper for default styling of a v-select, to work as v-chip-group? I also want the chips to work with the deletable-chips prop.
Component
<BaseSelect
multiple
class="flex-0-1-30rem"
localKey="breakdownBy"
:items="localizedBreakdownList"
:value="breakdowns"
:placeholder="$t('select-breakdownBy-label')"
#change="setBreakdowns"
>
<template v-slot:selection="{ item, select, index }">
<span
v-if="index === 0"
class="text--uppercase"
>{{ $t('select-breakdownBy-label') }}</span>
<v-chip color="primary" class="text--white">{{ item.text }}</v-chip>
</template>
</BaseSelect>
BaseSelect component
<template>
<v-select
hide-details
solo
dense
:append-icon="mdiMenuDown"
:items="items"
v-bind="$attrs"
v-on="$listeners"
>
<!-- Passes scopedSlots to child -->
<template v-for="(_, slot) of $scopedSlots" v-slot:[slot]="scope">
<slot :name="slot" v-bind="scope" />
</template>
<!-- Default scopedSlots -->
<template v-if="!hasScopedSlot('selection')" v-slot:selection="{ item }">
<span
:class="slotClasses"
>{{ item.text || $t(`select-${localKey}-option-${item.value || item}`) || item }}</span>
</template>
<template v-if="!hasScopedSlot('item')" v-slot:item="{ item }">
<span
:class="slotClasses"
>{{ item.text || $t(`select-${localKey}-option-${item.value || item}`) || item }}</span>
</template>
</v-select>
</template>

expand slot on data table not working inside wrapper component

expand slot on data table not working inside wrapper component
I have a wrapper component around v-data-table like so:
<template>
<div>
<wrapper-data-table
:headers="tableHeaders"
:items="partLines"
:expand="expand"
>
<template v-slot:items="line">
<tr #click="line.expanded = !line.expanded">
<td>{{ line.item.binLocation }}</td>
<td>{{ line.item.reqQuantity }}</td>
</tr>
</template>
<template v-slot:expand="line">
<v-card flat>
<v-card-text>Peek-a-boo!</v-card-text>
</v-card>
</template>
</wrapper-data-table>
</div>
</template>
Wrapper Data-Table component
<template>
<div>
<div>
<v-data-table
v-model="selected"
v-bind.sync="tableProps"
:expand="expand"
item-key="name"
>
<!-- Pass on all slots -->
<slot v-for="slot in Object.keys($slots)" :name="slot" :slot="slot" />
<!-- Pass on all scoped slots -->
<template v-for="slot in Object.keys($scopedSlots)" :slot="slot" slot-scope="scope">
<slot :name="slot" v-bind="scope" />
</template>
</v-data-table>
</div>
</div>
</template>
I'm passing through all scoped slots which mostly works fine. However the expand slot doesn't seem to work. I want to expand the row on row click just like the example in the docs.
It works if I'm using the data table directly without the wrapper. however, when it's wrapped, there is no expansion. I can see that the 'expanded' prop is being changed though.

How to use custom template for label in selected option in v-select?

I have used <template slot="option" slot-scope="option"> for custom label in v-select. Here, everything is working fine. The custom label is working fine when the options are opened as shown in the screenshot here: http://prntscr.com/kluu7p but the custom label is not working for selected option or when the select is closed: http://prntscr.com/kluudy .
Here is the snippet I have used to use custom template in v-select:
<v-select #input="updateShippingCharge"
v-model="selected"
:options="options">
<template slot="option" slot-scope="option">
<span :class="['flag-icon', `flag icon-${option.value.toLowerCase()}`]"></span>
{{ option.label }}
</template>
</v-select>
Add another template with attribute slot="selected-option".
<template slot="selected-option" slot-scope="option"></template>
The final code should look like this:
<v-select #input="updateShippingCharge"
v-model="selected"
:options="options">
<template slot="option" slot-scope="option">
<span :class="['flag-icon', `flag icon-${option.value.toLowerCase()}`]"></span>
{{ option.label }}
</template>
<template slot="selected-option" slot-scope="option">
<span :class="['flag-icon', `flag icon-${option.value.toLowerCase()}`]"></span>
{{ option.label }}
</template>
</v-select>