Using v-edit-dialog with components? - javascript

i had a question about the v-edit-dialog component that vuetify offers. So, the way i am rendering my v-data-table is such that i am importing a component with props into a template slot. According to the documentation link, it seems like the data table has to be rendered directly, like this codepen.
So i am not sure how i can make the v-edit-dialog work using my approach.
Here is what my code looks like:-
<template>
<v-data-table>
<template v-slot:items="props">
<my-component
:protein="props.item.protein"
:carbs="props.item.carbs"
:fats = "props.item.fats"
:iron="props.item.iron"/>
</template>
<v-data-table>
</template>
I am sorry guys, i don't know how i can duplicate this issue but i hope you get some idea. Again, thank you in advance.

You should take a look at the documentation for component props.
What you have done by now is correct and should work, only if you have setup your component my-component correctly:
<!-- my-component example -->
<template>
<v-edit-dialog :return-value.sync="protein">
{{ protein }}
<template v-slot:input>
<v-text-field
v-model="protein"
:rules="[max25chars]"
label="Edit"
single-line
counter
/>
</template>
</v-edit-dialog>
</template>
<script>
export default {
name: 'my-component',
props: {
protein: {
type: String,
default: '',
}, //... the rest of the props you want to access
},
}
</script>
In order to make the protein and other props edit/mutate/update your props.item.protein etc, you have to add a sync modifier to the prop.
<template>
<v-data-table>
<template v-slot:items="props">
<my-component
:protein.sync="props.item.protein"
:carbs.sync="props.item.carbs"
:fats.sync="props.item.fats"
:iron.sync="props.item.iron"/>
</template>
<v-data-table>
</template>
Else, you will get a vue error "you should not mutate an prop directly"

<template v-slot:items="props">.
for this eazy right is
<template v-slot:items="{ item }">
<my-component
{{item. protein}}

Related

Vue Slots: How to provide TypeScript types about available slot names and scoped slots?

I have created this example in the Vue Playuground
Let's imagine we have a third-party component coming from a library, the Card.vue component:
<template>
<slot name="slot1"></slot>
<slot name="slot2" title="I am slot 2">
</slot>
</template>
and this component is consumed within our application, where we leverage both a named slot and a scoped slot.
<script setup>
import Card from './Card.vue';
</script>
<template>
<Card>
<template #slot1>
<h1>
I am slot 1
</h1>
</template>
<template #slot2="slotProps">
<h1>
{{slotProps.title}}
</h1>
</template>
</Card>
</template>
However, coming from a React background where you don't have slots but rather children prop and Component props, what I struggle to understand is how to provide type information to a consumer.
How do I know, within my App.vue file, what slots name are available, and which scoped slot properties?

Cannot dynamically pass a prop to a component within a v-for loop in Vue js

I have an array sheets initialised in data, has an item pushed to it when a button is pressed
data() {
return {
sheets: []
};
}
And in the html I'm trying to add a Card component for each element in this array and pass the data as a prop, but none of the components get rendered and there is no error message. I also tried putting the v-for directly on the component but it has the same result
<div id="sheets">
<template v-for="c in sheets">
<Card :info="c"/>
</template>
</div>
Meanwhile if I do something like this, it displays all the data in the array correctly, so I dont understand whats going wrong here
<div id="sheets">
<template v-for="c in sheets">
<span>{{c}}</span>
</template>
</div>
--
Solution
In my component the data from prop was being manipulated in the created() function, it works after I did this in the mounted() function instead
Make sure you have following things done correctly:
Imported your Card component
Passing and accessing the props
There are no conflicts in the variable names and id names
Next thing you need to know and is a must while using v-for is adding :key to the element which acts as unique id and lets Vue detect that each element is unique inside the v-for. One thing to be noted while using :key is that, you cannot use :key on the <template> tag.
Adding a validation using v-if would be a good idea, so v-for only executes if the array is not empty.
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="(sheet,index) in sheets" :key="index" :info="sheet" />
</template>
</div>
Edit 1: As mentioned by Michal in the comments section that using index can lead to difficulties while debugging issues. You can use either :key="sheet" or if sheet is object including some unique id in it, then use :key="sheet.id" and get rid of the index
// use this if sheet is not an object
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="sheet in sheets" :key="sheet" :info="sheet" />
</template>
</div>
OR
// use this if sheet is an object having some unique id in it
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="sheet in sheets" :key="sheet.id" :info="sheet" />
</template>
</div>
As :key is not mandatory, It should work without that as well. I just created a working fiddle below. Please have a look and try to find out the root cause.
Vue.component('card', {
props: ['info'],
template: '<span>{{ info }}</span>',
});
var app = new Vue({
el: '#app',
data: {
sheets: [],
count: 0
},
methods: {
create() {
this.count++;
this.sheets.push('Sheet' + this.count);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="create">Create a Card!</button>
<template v-for="c in sheets">
<Card :info="c"></Card>
</template>
</div>

How would I implement an icon library (Tabler) in Vuetify?

I am using Vue2 and Vuetify in a project. I would like to be able to use any icon from the Tabler icon library, like so:
<v-icon>custom-icon-name</v-icon
I do not want to use the custom component based system with:
<v-icon>$vuetify.icons.iconName</v-icons>
Conceptually, what would be some possible solutions? Will I need to create a module for this, and if so, what would be a good approach? Thank you for your time.
The option that technically is working for me—but will be tedious to do—is to implement a TablerIcon.vue component:
<template>
<div>
<template v-if="iconName=='Deg360ViewIcon'">
<Deg360ViewIcon :size="size" :stroke-width="strokewidth" />
</template>
<template v-else>
<QuestionMarkIcon :size="size" :stroke-width="strokewidth" />
</template>
</div>
</template>
<style>
</style>
<script>
export default {
name: 'TablerIcon',
props: ['iconName','size','strokewidth'],
data() {
return {
}
},
}
</script>
And then I call this with:
import TablerIcon from './TablerIcon.vue'
...
components: {TablerIcon},
<TablerIcon :iconName="'Deg360ViewIcon'" :size="24" :strokewidth="1.5"/>
This seems to be working with the npm package found here: https://www.npmjs.com/package/vue-tabler-icons

Get date from slot in Vue

I got simplecomponent:
<template>
<v-chip>
<slot></slot>
</v-chip>
</template>
and I use it like that:
<formatted-date>2020-22-03</formatted-date>
how can I access the date given in the slot in the component?
If you need to manipulate the given data, use PROPS instead slots.
<template>
<v-chip>
{{ date }}
</v-chip>
</template>
<script>
...
props: ['date'],
...
</script>
And use it like that:
<formatted-date date="2020-22-03"></formatted-date>
This way you can access it using this.date inside the component.
Read more at: Official Docs - Props

Polymer dom-if doesn't restamp computed condition under dom-repeat

So I have a scenario:
<template is="dom-repeat" items="{{objects}}" as="o" filter="{{_filter(filter)}}">
...
<template is="dom-if" if="_isHidden" restamp>
foo
</template>
...
</template>
Now, the _filter function forces rerendering items under the dom-repeat every time my filter property changes (since it's observed by _filter. This is not the problem as it works properly, but the catch is that the _hidden function might return true or false based on another property (which could also change), and whenever the filter rerenders I need to force re-evaluation of _isHidden hence hide or show the contents of the dom-if template.
Anyone has an idea what could be my issue?
Thanks!
You have to also bind the _isHidden property:
<template is="dom-repeat" items="{{objects}}" as="o" filter="{{_filter(filter)}}">
...
<template is="dom-if" if="{{_isHidden}}" restamp>
foo
</template>
...
</template>

Categories

Resources