Get date from slot in Vue - javascript

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

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>

Vuejs b-table array template

I want to create a b-table template can understand data type and if it is array then it shows array keys one under the other. For example:
data.item.value may be :
string
array
json
<b-table :items="mydata">
<template #cell(name)="data">
<b-list-group-item>
{{data.item.value}}
</b-list-group-item>
</template>
</b-table>
if data.item.value is array should open new b-list-group-item automatically:
first b-list-group-item : data.item.value[0].name
second b-list-group-item : data.item.value[1].name
How can I handle this?
You would use v-for on the array inside your template. Then you can use v-if to special case type inside the group-item.
<b-table :items="mydata">
<template #cell="data">
<b-list-group-item v-for='value of data.item.value'>
{{value.name}}
</b-list-group-item>
</template>
</b-table>

How to call sessionStorage in <template> in Vuejs

Is there a way to call sessionStorage in section in Vuejs
Like
<template>
{sessionStorage}
</template>
When i call like this, i keep getting cant read property sessionStorage of null
if you want to show the data saved in sessionStorage in the template you should do this:
<template>
<div>{{ sessionStorage.getItem('someName') }} </div>
</template>
if you have JSON stored in sessionStorage and you want to show some property of that data you should parse it first like this:
<template>
<div>{{ JSON.parse(sessionStorage.getItem('someName')).propertyName }} </div>
</template>
but be careful because sessionStorage isn't a reactive data so if you change the storage after your vue component is rendered to DOM, you can't see the updated storage

Using v-edit-dialog with components?

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}}

Categories

Resources