How do I take the value of my v-for and step them in mounted() and data() in vue.js, and i have a problem with combobox, i'll explain below? - vuejs2

basically what I'm trying to do is, I get the DateTime coming from my database along with some information of a possible meeting, if people are busy, they will have the option to extend that time through a combobox that pulls a enum in my backend which has values ​​in milliseconds, description and id. As I get these values ​​coming from my enum, I can extend the meeting, but I did this validation on the frontend through a function... where I get the value of the combobox, and add it to the dateTime coming from the BE, however, I can't change the database (legacy) to add a field to save the enum, and that's why I had to make an adapted function in the frontend, and the extension method is hardcoded and doesn't have a field in the BE it replicates the same combobox for all. pointing out that I can't pull the data still coming from my v-for to mounted() or data().
Please help me. I'm using Primevue.
i tried to catch the index/code coming from the v-for by #click the dropdown by creating the function in mounted(), but without success. When trying to manipulate this data, it returns me an undefined value enter image description here
my v-for loop
`<div
class="mt-2"
v-for="(item, index) in listaAlarme"
:key="index">
<!-- {{ item.codigo }}
{{ index }} :{{ listaAlarme[index].referencia }} -->
<Card class="cardContainer">
<template #content>
<div class="formgrid grid">
<UnoFormField
id="dateTimeReference"
:cols="4"
label="Date and Time">
<UnoFormCalendar
v-model="listAlarm[index].reference"
#click="handleAlterTime(index)"
:withTime="true" />
</UnoFormField>
<UnoFormField
id="extended"
:cols="3"
label="Extended">
<Dropdown
v-model="typeActivitiesExtend"
:options="typeActivitiesExtendList"
option-label="description"
option-value="milliSeconds"
placeholder="Extended"
:class="{
'w-full': true,
}"
class="p-dropdown-uno-trigger-black"></Dropdown>
</UnoFormField>
<UnoFormField
id="contact.name"
:cols="3">
<div class="phoneIcon">
<fa-icon
icon="phone"
#click="handleCall" />
</div>
</UnoFormField>
</div>
</template>
<template #footer>
<div class="formgrid grid">
<!-- <div class="flex"> -->
<UnoFormField
id="meeting"
:cols="3">
<Button
icon="pi pi-search"
class="p-button-uno-black"
#click="handleMeeting"></Button>
</UnoFormField>
<UnoFormField
id="description"
:cols="3">
<p class="text">
{{ listAlarm[index].shortDescription }}
</p>
</UnoFormField>
<div class="iconButtons">
<fa-icon
icon="ban"
class="banIcon"
#click="excludeItem" />
<fa-icon
icon="check"
class="checkIcon"
#click="onBtnSave" />
</div>
<!-- </div> -->
</div>
</template>
</Card>
`
the UnoFormField, is a label as you can see, that me return the label name and fied col just for display de fields with a size col in template
my function to extend the hours in methods:
i'm try to catch the value of datatime in v-for
`

Related

Handling button in multiple Cards

I've product listing page where I use multiple ProductCard component. I need to add Spinner to Add to cart button when clicking on it, but if I just add Spinner to v-else I've Spinners in every ProductCard. How to control only this ProductCard where I click Add to cart button?
Parent's component:
<ProductCard
v-for="product in products"
:key="product.id"
:product="product"
/>
Child's component:
<template>
<div id="productCart">
<div>
<NuxtLink :to="`/product/${item.slug}`" />
<NuxtLink v-if="item.name" :to="`/product/${item.slug}`">
<h5
id="productName"
v-text="item.name"
/>
</NuxtLink>
<Button
v-if="!loading"
#click="addToBuyCart({ product: item })"
v-text="$t('labels.buy')"
/>
<Spinner v-else />
</div>
</div>
</template>
loading is defined in composable, and it's updating in addToBuyCart function by making it true, then adding to cart (api), then making it false
As pointed by IVO, in such situations you should check against a value specific for each item in the loop, item ID for example, instead of a boolean which lacks specificity and therefore cannot be used for such scenarios.
<template>
<div id="productCart">
<div>
<NuxtLink :to="`/product/${item.slug}`" />
<NuxtLink v-if="item.name" :to="`/product/${item.slug}`">
<h5
id="productName"
v-text="item.name"
/>
</NuxtLink>
<Button
v-if="loading !== item.id"
#click="addToBuyCart({ product: item })"
v-text="$t('labels.buy')"
/>
<Spinner v-else />
</div>
</div>
</template>
const addToBuyCart = ({product}) => {
loading = product.id
// some logic or request
loading = null
}

How do I retrieve the value of my key button and row in v-for using Vue.js?

I am new to Vue.js and I trying to learn now to use it. I have 3X3 structure of buttons
I have the following sample code:
<template v-for="row in 3">
<div class="row" :key="row">
<button #click="nextPlayer(button, row)" v-for="button in 3" :key="indexByrow(button, row)" :value="squares[indexByrow(button, row)]" class="square" style="width:40px;height:40px;"></button>
</div>
</template>
When I click, I want to pass the button and row to nextPlayer(button, row), and the indexByrow(button, row) to use those values in the methods, but I don't seem to have any values. My main goal is to change the value name when I click on it.
You need to make the below changes
<template v-for="(row, indx) in 3">
<div class="row" :key="indx">
<button #click="nextPlayer(button, row)" v-for="(button, indexer) in 3" :key="indexer" :value="squares[indexByrow(button, row)]" class="square" style="width:40px;height:40px;"></button>
</div>
</template>
Not sure if indexByrow is a computed property or method.
You need to modify the logic in indexByrow as well based on the above changes

Vue Component that Can Override What Child Renders Dynamically

I am working on a component (InfoCard) that should be able to render any number of fields passed into it with a 'fields' prop, as an array of json objects with a name, value, and some styling options. For certain fields, I want to be able to override what component is used to render, but do it from the parent (Table) rather than inside the InfoCard component, as it should be generic. My first thought was to use a <component :is='field.component'></component>, where it will render as plaintext if field.component is not defined, but to my understand it will be difficult to pass in any potential children necessary for the <component/>. My second thought is to use named slots from within the parent, but I don't think this is possible either in a good way. I'll show my current code.
In my example, I want to be able to detect if the field being rendered is 'status', and if it is, use a different rendering mechanism than displayValue(attribute), without hardcoding it inside InfoCard; I want the parent to be able to override this rendering conditionally. Is there a way to do this in Vue? Thanks
From Table, where data.records is an array of JSON objects:
<info-card
v-for="(record,index) in data.records"
:key="index"
:fields="record"
>
<div v-for="key in Object.keys(record)" :key="key">
<template v-if="field.name=='status'" v-slot:[`${field.name}_value`]>
<p> Field is status !</p>
</template>
</div>
</info-card>
From InfoCard:
<template>
<el-col
:lg="3"
:md="3"
:sm="3"
:xs="3"
v-for="(attribute, index) in fields"
:key="index"
class="attribute"
>
<div
#click="$emit('fieldClicked', attribute)"
>
<el-row
:class="`mid-gray f6 clipped fw5-ns m-b-10 ${attribute.nameClasses}`"
:title="displayName(attribute)"
:style="attribute.nameStyle?attribute.nameStyle:''"
>
<slot
v-if="Object.keys($scopedSlots).includes(`${attribute.name}_name`)"
:name="$scopedSlots[`${attribute.name}_name`]"
>
</slot>
<div v-else>
{{ displayName(attribute) }}
</div>
</el-row>
<el-row
:class="`mid-gray f6 clipped fw5-ns m-b-10 ${attribute.valueClasses}`"
:title="displayValue(attribute)"
:style="attribute.valueStyle?attribute.valueStyle:''"
>
<slot
v-if="Object.keys($scopedSlots).includes(`${attribute.name}_value`)"
:name="$scopedSlots[`${attribute.name}_value`]"
>
</slot>
<div v-else>
{{ displayValue(attribute) }}
</div>
</el-row>
</div>
</el-col>
</template>

Assign all data to all slots

Is there a better way to assign my data to all my slots, without needing to bind this on each individual slot?
So currently i'm doing:
<slot name="header" :data="this._data">
<header>
<h2>{{ header }}</h2>
<p>{{ subtitle }}</p>
</header>
</slot>
This in order to use the data I must do this:
<finance-calculator class="app" vehicle-id="1815981">
<template #header="data">{{ data.data.header }}</template>
</finance-calculator>
I tried to use the render method to assign the data however this doesn't appear to work at all:
render() {
const data = this._data;
return this.$scopedSlots['header']({
test: 'hello'
});
},
Can someone help me out here?
You just can use $data to refer to the data object of a component. Like this:
<slot name="header" :data="$data">
<header>
<h2>{{ header }}</h2>
<p>{{ subtitle }}</p>
</header>
</slot>
<finance-calculator class="app">
<template #header="{data}">{{ data.header }}</template>
</finance-calculator>

How to use "v-for", for array in computed object

I am creating a website to list all of my projects. I am using Vuex and Firebase to store all my data.
I want each project to have its own "todo-list".
When I create a new project, I create an array witch is my todo-list. In Firebase it looks like this: Screenshot of Firebase
Now I want to display a list of my projects. First I get my projects as a computed prop like this:
<script>
export default {
computed: {
projects () {
return this.$store.getters.loadedProjects
}
},
created () {
this.$store.dispatch('loadProjects')
},
}
</script>
I can loop through projects and display the title for each project.
My question is: how do I loop through the todo-array inside the computed prop?
<template>
<div v-for="project in projects" :key="project.id">
<p>{{ project.title }}</p>
<!-- Looping through todos (array) in an computed prop -->
<div v-for="(todo, index) in todos" :key="todo.id">
<p>{{ project.todos[index].title }} </p>
<p>{{ project.todos[index].completed }} </p>
</div>
</div>
</template>
Tried to use the computed prop inside v-for, but that does not work.
Not sure if I understand the meaning of computed properties. Could I just define projects () inside data () ? and link the getter to the data?
<div v-for="todo in {{project.todos}} :key="todo.id>
If the second loop is inside the first one, you could access it this way:
<template>
<div v-for="project in projects" :key="project.id">
<p>{{ project.title }}</p>
<!-- Looping through todos (array) in an computed prop -->
<div v-for="todo in project.todos" :key="todo.id">
<p>{{ todo.title }} </p>
<p>{{ todo.completed }} </p>
</div>
</div>
</template>
When you create a loop, in this case, project is a single element of the array, so project.todos is the list of todos of that specific project.
https://v2.vuejs.org/v2/guide/list.html#Mapping-an-Array-to-Elements-with-v-for