Change <v-autocomplete> chip delete icon - vuejs2

Autocomplete.vue
<template>
<v-autocomplete
v-bind="$props"
v-on="$listeners"
>
<!-- Cycling through slots -->
<template v-for="(_, name) in $slots">
<template :slot="name">
<slot :name="name"></slot>
</template>
</template>
<!-- Cycling through scoped slots -->
<template
v-for="(_, name) in $scopedSlots"
#[name]="data"
>
<slot
:name="name"
v-bind="data"
></slot>
</template>
</v-autocomplete>
</template>
<script>
import { VAutocomplete } from 'vuetify/lib'
export default {
extends: VAutocomplete,
props: {
dense: {
default: true
},
smallChips: {
default: true
}
}
}
</script>
I want to change the trash icon.
I looked in the documentation, but I didn't find any prop able to directly change the icon. I might be wrong, and I hope so, but it could be necessary to access the item slot to change the icon.
If so, can anyone provide the necessary code to change the icon WITHOUT losing any feature/functionality?

try the clear-icon prop.
from the documentation-

Related

<v-dialog> value prop doesn't work when extending component

I created a FormDialog component which extends v-dialog
FormDialog
<template>
<div>
<v-dialog
v-bind="$props"
:value="dialog"
:transition="false"
scrollable
persistent
no-click-animation
#keydown.ctrl.enter="handleSave"
#keydown.esc="handleCancel"
#click:outside="handleCancel"
>
<v-card>
<v-card-title>
<!-- title -->
</v-card-title>
<v-card-text>
<v-container>
<slot name="form">
missing form slot
</slot>
</v-container>
</v-card-text>
<v-card-actions>
<!-- actions -->
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { VDialog } from 'vuetify/lib'
export default {
extends: VDialog,
props: {
/* Custom props */
/* Direct binding to value prop doesn't work */
dialog: undefined
},
methods: {
handleSave () {
this.$emit('save')
},
handleCancel () {
this.$emit('cancel)
}
}
}
</script>
As you can see I'm using a prop named dialog binded to v-dialog value prop, because direct value usage doesn't work.
ChildComponent (using value, doesn't work)
<FormDialog
:value="showDialog"
#save="handleSave"
#cancel="handleCancel"
>
<!-- form -->
</FormDialog>
Obviously I removed dialog prop references.
ChildComponent (using dialog, works)
<FormDialog
:dialog="showDialog"
#save="handleSave"
#cancel="handleCancel"
>
<!-- form -->
</FormDialog>
Do anyone knows the answer? I'd like to use value prop directly.

Vue layout with named slots

Is it possible?
I have something like this:
<template>
<my-layout>
<template #header>
Some header html goes here
</template>
Body html here
</my-layout>
</template>
<script>
import MyLayout from './MyLayout.vue'
export default {
layout: MyLayout,
components: {
//MyLayout
}
}
</script>
And template like that
<template>
<div>
<slot name="header"/>
</div>
<slot/>
</template>
The default slot works, but "header" slot doesn't display itself (unless using MyLayout as standard component).
I believe there is a problem with the closing tags on the template you have given and it should be like the following:
<template>
<div>
<slot name="header"> </slot>
</div>
</template>
After that, layout property only excepts strings or functions that return strings, so parent should be like the following:
<template>
<my-layout>
<template #header>
Some header html goes here
</template>
Body html here
</my-layout>
</template>
<script>
import MyLayout from "./MyLayout.vue";
export default {
layout: "MyLayout",
components: {
//MyLayout
}
};
</script>
I hope this solves your problem and have a nice day :)

Executing js on slot

I'm a beginner in web development and I'm trying to help out friends restarting an old game. I'm in charge of the tooltip component but I hit a wall...
There are many Vue components and in a lot of them I want to call a child component named Tooltip, I'm using vue-tippy for easy configuration. This is the component:
<template>
<tippy class="tippy-tooltip">
<slot name='tooltip-trigger'></slot>
<template #content>
<slot name='tooltip-content'>
</slot>
</template>
</tippy>
</template>
<script>
import { formatText } from "#/utils/formatText";
export default {
name: "Tooltip",
methods:{
formatContent(value) {
if (! value) return '';
return formatText(value.toString());
}
},
}
</script>
In one of the other components I try to use the tooltip:
<template>
<a class="action-button" href="#">
<Tooltip>
<template #tooltip-trigger>
<span v-if="action.movementPointCost > 0">{{ action.movementPointCost }}<img src="#/assets/images/pm.png" alt="mp"></span>
<span v-else-if="action.actionPointCost > 0">{{ action.actionPointCost }}<img src="#/assets/images/pa.png" alt="ap"></span>
<span v-if="action.canExecute">{{ action.name }}</span>
<span v-else><s>{{ action.name }}</s></span>
<span v-if="action.successRate < 100" class="success-rate"> ({{ action.successRate }}%)</span>
</template>
<template #tooltip-content>
<h1>{{action.name}}</h1>
<p>{{action.description}}</p>
</template>
</Tooltip>
</a>
</template>
<script>
import Tooltip from "#/components/Utils/ToolTip";
export default {
props: {
action: Object
},
components: {Tooltip}
};
</script>
From here everything is fine, the tooltip is correctly displayed with the proper content.
The thing is, the text in the {{ named.description }} needs to be formatted with the formatContent content. I know I can use the props, the components would look like that:
Tooltip.vue:
<template>
<tippy class="tippy-tooltip">
<slot name='tooltip-trigger'></slot>
<template #content>
<h1 v-html="formatContent(title)" />
<p v-html="formatContent(content)"/>
</template>
</tippy>
</template>
<script>
import { formatText } from "#/utils/formatText";
export default {
name: "Tooltip",
methods:{
formatContent(value) {
if (! value) return '';
return formatText(value.toString());
}
},
props: {
title: {
type: String,
required: true
},
content: {
type: Array,
required: true
}
}
}
</script>
Parent.vue:
<template>
<a class="action-button" href="#">
<Tooltip :title="action.name" :content="action.description">
<template v-slot:tooltip-trigger>
<span v-if="action.movementPointCost > 0">{{ action.movementPointCost }}<img src="#/assets/images/pm.png" alt="mp"></span>
<span v-else-if="action.actionPointCost > 0">{{ action.actionPointCost }}<img src="#/assets/images/pa.png" alt="ap"></span>
<span v-if="action.canExecute">{{ action.name }}</span>
<span v-else><s>{{ action.name }}</s></span>
<span v-if="action.successRate < 100" class="success-rate"> ({{ action.successRate }}%)</span>
</template>
</Tooltip>
</a>
</template>
<script>
import Tooltip from "#/components/Utils/ToolTip";
export default {
props: {
action: Object
},
components: {Tooltip}
};
</script>
But I need to use a slot in the tooltip component because we'll have some "extensive" lists with v-for.
Is there a way to pass the data from a slot into a JS function?
If I understand you correctly, you're looking for scoped slots here.
These will allow you to pass information (including methods) from child components (the components with <slot> elements) back to the parents (the component(s) filling those slots), allowing parents to use chosen information directly in the slotted-in content.
In this case, we can give parents access to formatContent(), which will allow them to pass in content that uses it directly. This allows us to keep the flexibility of slots, with the data passing of props.
To add this to your example, we add some "scope" to your content slot in Tooltip.vue. This just means we one or more attributes to your <slot> element, in this case, formatContent:
<!-- Tooltip.vue -->
<template>
<tippy class="tippy-tooltip">
<slot name='tooltip-trigger'></slot>
<template #content>
<!-- Attributes we add or bind to this slot (eg. formatContent) -->
<!-- become available to components using the slot -->
<slot name='tooltip-content' :formatContent="formatContent"></slot>
</template>
</tippy>
</template>
<script>
import { formatText } from "#/utils/formatText";
export default {
name: "Tooltip",
methods: {
formatContent(value) {
// Rewrote as a ternary, but keep what you're comfortable with
return !value ? '' : formatText(value.toString());
}
},
}
</script>
Now that we've added some scope to the slot, parents filling the slot with content can use it by invoking a slot's "scope":
<!-- Parent.vue -->
<template>
<a class="action-button" href="#">
<Tooltip>
. . .
<template #tooltip-content="{ formatContent }">
<!-- Elements in this slot now have access to 'formatContent' -->
<h1>{{ formatContent(action.name) }}</h1>
<p>{{ formatContent(action.description) }}</p>
</template>
</Tooltip>
</a>
</template>
. . .
Sidenote: I prefer to use the destructured syntax for slot scope, because I feel it's clearer, and you only have to expose what you're actually using:
<template #tooltip-content="{ formatContent }">
But you can also use a variable name here if your prefer, which will become an object which has all your slot content as properties. Eg.:
<template #tooltip-content="slotProps">
<!-- 'formatContent' is now a property of 'slotProps' -->
<h1>{{ slotProps.formatContent(action.name) }}</h1>
<p>{{ slotProps.formatContent(action.description) }}</p>
</template>
If you still need the v-html rendering, you can still do that in the slot:
<template #tooltip-content="{ formatContent }">
<h1 v-html="formatContent(title)" />
<p v-html="formatContent(content)"/>
</template>

Deep in slots vue 2

Does anybody know is there are some limitations on how deep my components with slots can be ?
Now I have 3 components, like
list.vue
<div class="list">
<slot name="list" />
</div
wrapper.vue
<list>
<template #list>
<div>hello</div>
<slot name="wrapper" />
</template>
</list>
last.vue
<wrapper>
<template #wrapper>
<search :value=value />
</template>
</wrapper>
So, i want to transfer some value from last component to search component. On init something is good, but if value is changing in my last component my search component it doesn't see.
Maybe someone know information about max deep for components + slots ?
You forgot to share your Search component and the rest of the other components (namely, the script section). There is no limit in the slot depth (whatever that means). I'm assuming you have some other errors in parts you haven't shared. My first guess would be the way you have set the props in your Search component.
Here is an example of a working version on how you should set a nullable prop on a component:
Last.vue
<template>
<Wrapper>
<template #wrapper>
<label>
<input type="text" v-model="value">
</label>
<Search :value=value />
</template>
</Wrapper>
</template>
<script>
import Wrapper from "#/components/Wrapper";
import Search from "#/components/Search";
export default {
components: {Search, Wrapper},
data() {
return {
value: null
}
}
}
</script>
Search.vue
<template>
<p>{{ value }}</p>
</template>
<script>
export default {
props: {
value: {
type: String,
default: null,
}
},
}
</script>
If this doesn't address your problem, please share the rest of your code and I'd be glad to help!

Passing value from parent to child using slot probably

I probably don't understand how it should be done. I spent a few hours to achieve this functionality but with no luck. Here is what I have:
Child
<template>
<div>
Data from dialog: {{aaa}}
</div>
</template>
<script>
export default {
name: 'frm',
props: [
'aaa'
]
}
</script>
Parent:
<template>
<div>
<slot :aaa="some"></slot>
</div>
</template>
<script>
export default {
name: 'dlg',
data: () => ({
some: 'data from dialog'
})
}
</script>
View:
<template>
<div>
<dlg>
<frm></frm>
</dlg>
</div>
</template>
<script>
import Dialog from '#/components/dialog.vue'
import Frm from '#/components/frm.vue'
export default {
name: "View",
components: {
'dlg': Dialog,
'frm': Frm
}
};
</script>
Edit: Real code
dialog-template:
<template>
<v-dialog
v-model="internal.dialogOpened"
>
<!-- ... -->
<slot :aaa="'dsada'"></slot>
</v-dialog>
</template>
details-task-dialog:
<template>
<dlg-template large position='right' :onclose="close" :load="loadRetry">
<task-details-form /> <!-- just regular component in which I want to get value passed through slot in dialog-template -->
</dlg-template>
</template>
<script>
import DlgTemplate from '#/components/site/dialogs/dialog-template.vue'
export default {
// ...
components: {
'dlg-template': DlgTemplate,
'task-details-form': DetailsForm,
},
I want to avoid passing prop in View but I don't know how :/ I've read about 'slot-scope' unfortunately with no success. How to achieve such functionality?
Edit: real code
Based on your real world code, you were only missing the attachment of the scope, see below.
dialog-template:
<template>
<v-dialog v-model="internal.dialogOpened">
<!-- ... -->
<slot :aaa="'dsada'"></slot>
</v-dialog>
</template>
details-task-dialog:
<template>
<dlg-template large position='right' :onclose="close" :load="loadRetry">
<task-details-form v-slot="{ aaa }">
<!-- you can use the var `aaa` here -->
</task-details-form>
</dlg-template>
</template>
I'd still wager if you want to use aaa inside task-details-form component you have to pass it down as a prop. But it looks wierd to me, because I'm unsure of the execution order right now (v-slot vs v-bind), but try it like this:
<template>
<dlg-template large position='right' :onclose="close" :load="loadRetry">
<task-details-form v-slot="{ aaa }" :your-a-prop-name="aaa" />
</dlg-template>
</template>
Edit 2: after testing
v-bind shorthand is not working on <slot>:
dialog-template:
<template>
<v-dialog v-model="internal.dialogOpened">
<!-- ... -->
<slot v-bind:aaa="'dsada'"></slot>
</v-dialog>
</template>
details-task-dialog:
<template>
<dlg-template large position='right' :onclose="close" :load="loadRetry">
<template v-slot="{ aaa }"> <!-- has to preceed v-bind -->
<task-details-form :propertyOnComponent="aaa" /> <!-- now you cand bind it -->
</template>
</dlg-template>
</template>
Original:
I think you misunderstood slots. Check the docs:
That slot has access to the same instance properties (i.e. the same “scope”) as the rest of the template. The slot does not have access to child’s scope.
Slots
So you could do that, but then your code becomes:
<template>
<div>
<dlg>
<frm>
<child :aaa=“dialogData” />
</frm>
</dlg>
</div>
</template>
Frm:
<template>
<div>
From component
<slot></slot>
</div>
</template>
If you would define a slot on frm as you are suggesting, you would be able to fill that slot with a specific template and you can receive(!) the scope for that slot.
The deprecated slot-scope which you mentioned would provide you with a bound context from the child to be exposed in your overriding slot in the parent, that’s the opposite of what you want.
Just out of curiosity, why not send down the dialog data to the form as a property? That’s exactly what it’s for.