Using inner component in a loop in Shopware 6 does not persist the values uniquely for each looped component - vuejs2

I am using a v-for over a custom component and passing the item as a prop. But the issue is that each component instance in the loop takes the same item prop. For e.g in the 1st loop a component field has text "abc", then the second looped component also will have the same "abc" text. If I change the text in the 2nd one, it changes in the 1st component too. Is there a way to make the prop unique for each loop ?
For e.g this is the code which calls the inner component:
<template v-for="(businesscase, index) in businessCase.fields">
<custom-case-freetext-field #field-changed="updateFields"
:key="index"
#field-removed="removeFields"
:fields="businessCase.fields"
:index="index">
</custom-case-freetext-field>
</template>
and inside this component I have a basic form
<sw-field :label="$tc('rma.modules.case.freetext.nameLabel')"
:placeholder="$tc('rma.modules.case.freetext.nameLabel')"
required
v-model="fields[index].name">
</sw-field>
<sw-single-select
labelValue="label"
valueProperty="label"
:options="fieldTypes"
:label="$tc('rma.modules.case.freetext.fieldType')"
:placeholder="$tc('rma.modules.case.freetext.fieldType')"
v-model="fields[index].type"
#input="changeType"
required>
</sw-single-select>
If I do :value instead of v-model, the entered value disappears as soon as the element loses focus.
If I use v-model, the data stays there, but then both (or as many are there in the loop) component instances, have data binding between them, so it defeats the purpose of having a loop for multiple components. As seen in the screenshot, I am typing in the 2nd component, but it changes the text for the first one too.
In the above example I am sending the whole array as prop, but I have also tried with individual field element instead of fields

Your are not using the businesscase variable inside your components. And since every component always works on the upper scope property, they will all change the same. Use the innerscope property. If you have problems with reactivity, because you try to mutate props directly work with events emitting the key and the changed value to the upperscope component.

Related

Send template to grandchild component (nested template)

There is this TablePackage component that we use in our project. I saw that to customize how values in a column render, one can pass template named with the specific column name (in this example status) and use slot prop row.
<!--Code Snippet 1-->
<!--In each row of status columns, we will see status buttons instead of plain status text-->
<TablePackage>
<template #status="{ row }">
<button>{{ row.status }}</button>
</template>
</TablePackage>
Now there are two more components, Parent and Dialogue.
Parent uses Dialogue, Dialogue uses TablePackage.
Parent component
<Dialogue title="dialogueTitle">
</Dialogue>
Dialogue component
{{ title }}
<TablePackage rows="rowList" columns="columnObj">
</TablePackage>
Now I want to be able to custom render values in a column as in 'Code Snippet 1' which means I want to render a button not a text in 'status' column. How can I achieve this from Parent component level? I tried nested template but it was not allowed. With the constraint that I can edit Parent and Dialogue components but not TablePackage, what's the recommended away to achieve this?

How fix datepicker calendar position in element-ui

I have two datepickers in my code and i change them between each other by another parameter(duration which can be Single day or Multi day). By default it set as Single day. First calendar have right position, but when i change from single day to multi day and open range datepicker, calendar which have absolute position sets in top left corner of page (with top:0;left:0 parameters).
I tried change directive v-if to v-show in my code below, and it helps, but there is another problem. For some reason element-ui think that picked value is not range and throw parse error. So i need another solution.
That's piece of code with this datepickers:
<el-date-picker
v-if="duration === durations.SingleDay"
placeholder="Enter date"
value-format="yyyy-MM-dd"
#input="updateTime($event, 'dateValue')"
:value="value.dateValue"
></el-date-picker>
<el-date-picker
v-else-if="duration !== durations.SingleDay"
placeholder="Enter date"
type="daterange"
value-format="yyyy-MM-dd"
:value="value.dateValue"
#input="updateTime($event, 'dateValue')"
></el-date-picker>
I want to positionate range datepicker as usual, like in datepicker in Single day parameter.
FIDDLE
Demo on fiddle, first open calendar and change type and reopen it, you can see this bug
In that case, there're two ways to solve this:
Change v-if to v-show
Add different key attributes to the Datepicker components (Vue will know that this is two different components)
In fact, this is not a bug. You use the same component in v-if and v-else. The two component properties are basically the same, so Vue will reuse the previous components, but you should avoid multiplexing complex components in Vue. It's easy to go wrong, which is why you must add a key in v-for in vue.
You did not modify the internal reference this.$refs.reference when you reused the component, and the position of the popover cannot be calculated correctly.

Vue remove child component with it state

I want delete child component. I use this.rows.splice(index, 1)
When i call this.rows.splice(index, 1) VueJs always remove last component from this.$children and save internal state in component.$data ;
Example is here
`https://jsfiddle.net/abratko/gc7h1r34/3/`
How fix it?
Vue associates each data item with each vnode according to the item's index by default. This results in existing Vue components being reused, but bound to different items, when re-rendering the list after an item was removed from the array.
This is why you should always bind key to a value which uniquely identifies that particular item. In your example, since each item is a unique string you can just bind to that:
<row-component v-for="(row, index) in rows" :key="row">
^^^^^^^^^^

VueJS vee-validate issue when passed validation as props to input component

I'm building an input component to work with vee-validate.
for more convenience, I want to use validation rules as a props for this.
Every thing is ok when I use v-model directive on parent. but, with value property; after writing in the field and validating, input value reset to it's parent.
This is logical? if not, how can I solve this problem without v-model?
Note that:
1) - Validations events are 'input' and 'blur'
2) - I never want to set v-on:input event on parent
See This Fiddle
This is logical.
#input="$emit('input', $event.target.value)" is useless here because you don't listen to the input event.
When your input is invalid, component is re-render again. value of input component has never change changed when you input. When it re-render, it will display correct value which is passed from parent.
https://jsfiddle.net/787g7q0e/

Vue.js - 2 way binding not working. Data is not updating when changed in a component

I have a 'Builder' component and I am passing a variable named 'formula' to that component, but the changes made in this variable in 'Builder' component do not get updated in current component.
<builder :formula="formula"
:columns="columns"
:result_type="result_type">
</builder>
When I submit form the value for the 'formula' variable is same.
try this
<builder :formula.sync="formula"
:columns="columns"
:result_type="result_type">
</builder>
As in VueJS 2 .sync - 2 way binding has been deprecated, you have to handle it differently. https://v2.vuejs.org/v2/guide/migration.html#once-and-sync-Modifiers-on-v-bind-removed
You have to emit events like this.$emit('formulaChange', formula) etc. and listen to them in parent component with #formulaChange=yourHandler(formula)