Update value in dynamic object in vuex store in Nuxt - javascript

In my Vue/Nuxt project I have a form where the user can add update dynamic fields to be used in a price offer calculation.
When the form loads there will be created one field with the beforeMount lifecycle, and the user can then choose to create one or more extra fields.
in my data return I have this:
data() {
return {
calculationFields: { qty: 0, price: 3.86, selected: false },
}
}
And when the user click the "Add field" button the addField method is called:
addField() {
this.$store.dispatch('quantity/updateAdd', this.calculationFields)
},
where the updateAdd actions calls the UPDATE_ADD_ITEM mutation
UPDATE_ADD_ITEM(state, value) {
state.options.push(value)
},
value is { qty: 0, price: 3.86, selected: false }
this works fine as the options array is updated with the new field object
In the template I loop on this array to output X number of fields
<div v-for="(field, index) in getCalculationFields()" :key="field" class="flex-xs justify-between calculation-field">
<InputCustomPlaceholder type="number" :is-required="true" :input-id="`calculation-${index}`" :input-name="`calculation-${index}`" label-text="" placeholder-text="Add pieces" custom-placeholder-text="pcs" extraclass="flex-1 no-margin" />
×
</div>
My problem now is, that I can't figure out how I can use v-model on each dynamically created input fields so that I can update the qty value in the field object in the options state.
So if the list contains three fields like:
[
{ qty: 0, price: 3.86, selected: false },
{ qty: 0, price: 3.86, selected: false },
{ qty: 0, price: 3.86, selected: false }
]
So when the use in field number 2 input 200 as quantity the array will look like this:
[
{ qty: 0, price: 3.86, selected: false },
{ qty: 200, price: 3.86, selected: false },
{ qty: 0, price: 3.86, selected: false }
]
I believe I have to use something like
<InputCustomPlaceholder type="number" :is-required="true" :input-id="`calculation-${index}`" v-model="updateOptionList" :input-name="`calculation-${index}`" label-text="" placeholder-text="Add pieces" custom-placeholder-text="pcs" extraclass="flex-1 no-margin" />
But what is the best what to find the index of the field and update the value in that index on the array.
In a non-dynamic input I use something like this:
v-model="updateFieldOne"
updateFieldOne: {
set(value) {
this.$store.dispatch('fields/updatePartDimeWidth', value)
}
}
which works as intended.

You can give index props, and use it in mutation. EDIT_ITEM mutation help for edit item if you want add new elemenet use state.options.push(value).
this.$store.dispatch('fields/updatePartDimeWidth', {value ,index})
EDIT_ITEM(state, {value ,index }) {
state.options[i] = value
},

Related

disable current selection until some value is inputed in the previous selection

I'm working with BootstrapVue.
I have following problem. I have a b-form-input where I'm searching for my number over my b-form-select. So I'm selecting 3 values and get a number in my input field and other way around - so it's an Autofill.
This works fine - and because of that I think I don't need to show you the code.
The problem is that I want to disable all selects (instead of the first) till the field before was selected.
I have problem that if I have multiple elements all will be updated. So if I input something in Input1 in the first element the second Input of all other elements will be !disabled
Additional Info: IDParent is a prop!
If you need any additional code, I can update my question!
<template>
<div>
<div class="mt-2" v-for="(IDChild, indexChild) in inputs" :key="indexChild">
<div>
<div class="mt-2">Number</div>
<b-form-input type="number" v-model="IDChild.Number" :value="IDChild.Number"></b-form-input>
</div>
<div>
<div class="mt-2">Input 1</div>
<b-form-select v-model="IDChild.Input1" :value="IDChild.Input1" :options="optionsInput1" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 2</div>
<b-form-select :disabled="disabledInput2" v-model="IDChild.Input2" :value="IDChild.Input2" :options="optionsInput2" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 3</div>
<b-form-select :disabled="disabledInput3" v-model="IDChild.Input3" :value="IDChild.Input3" :options="optionsInput3" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
</div>
<!-- add new element when button was clicked -->
<div class="mt-4 mb-5 ml-3 mr-3">
<b-button #click="addElement"> Add Element </b-button>
</div>
</div>
</template>
my script:
<script>
import json from "./json/json.json";
export default {
name: "Test",
methods: {
addElement() {
this.inputs.push({});
},
searchNumber(input, IDParent, indexChild) {
input.Number = "";
this.json.forEach((element) => {
if (
element.Input1 == input.Input1 &&
element.Input2 == input.Input2 &&
element.Input3 == input.Input3
) {
for (const key of Object.keys(element)) {
input[key] = element[key];
}
}
});
if(input.Input1) {
this.disabledInput2 = false;
}
if(input.Input2) {
this.disabledInput3 = false;
}
},
},
props: [
"IDParent",
],
data() {
return {
inputs: [{}],
json: json,
disabledInput2: true,
disabledInput3: true,
};
},
};
</script>
What you are missing is a multi-layer model for your data which you can call in your searchNumber function and call for your :disabled attribute.
In your v-for="(IDChild, indexChild) in inputs" you could use IDChild or indexChild for that. For example you would call :disabled="disabledInput2[indexChild]". That way you would refer to disabledInput2 with the specific indexChild.
You also need to handle this in your function, for example this.disabledInput2[indexChild] = false;.
Basically it´s the same as storing multi-layer data in the same object with v-model.
EDIT: Generally Example
I´ve created the following properties for this example. We have myNumberInput as an object to handle multiple input fields for numbers. mySelectionData provides a simple collection of two objects with 3 selection arrays each. myDisableData is the object that will handle multiple disabled attributes for this selections:
myNumberInput: {},
mySelectionData: {
1: {
1: [
{ name: "1A", value: 1 }, { name: "2A", value: 2 }, { name: "3A", value: 3 }
],
2: [
{ name: "4A", value: 4 }, { name: "5A", value: 5 }, { name: "6A", value: 6 }
],
3: [
{ name: "7A", value: 7 }, { name: "8A", value: 8 }, { name: "9A", value: 9 }
]
},
2: {
1: [
{ name: "1B", value: 11 }, { name: "2B", value: 21 }, { name: "3B", value: 31 }
],
2: [
{ name: "4B", value: 41 }, { name: "5B", value: 51 }, { name: "6B", value: 61 }
],
3: [
{ name: "7B", value: 71 }, { name: "8B", value: 81 }, { name: "9B", value: 91 }
]
}
},
myDisableData: {}
From the mySelectionData object, we will build our myDisableData with this function:
setupMyDisableData() {
Object.keys(this.mySelectionData).forEach(parent_key => {
Object.assign(this.myDisableData, {[parent_key]: {}})
Object.keys(this.mySelectionData[parent_key]).forEach(child_key => {
Object.assign(this.myDisableData[parent_key], {[child_key]: true})
});
});
}
This will loop trough our "parents", assign their index to myDisableData and also loop trough the "childs" and assign their index to myDisableData with the "parent"-index as a pointer. After that we have a multi-layer object which is able to provide diabled= true or false for each selection.
The html for this example looks like this:
<div v-for="(item,index) in mySelectionData" :key="index">
<input type="number" v-model="myNumberInput[index]" #input="enableMySelection(index, myNumberInput[index])">
<div v-for="(child_item, child_index) in item" :key="child_index">
<select :disabled="myDisableData[index][child_index]">
<option v-for="(child_option, child_option_index) in child_item" :key="child_option_index" :value="child_option.value">{{child_option.name}}</option>
</select>
</div>
</div>
As I don´t use BootstrapVue, my html looks different, but I guess you will get the trick. You simply now refer to the three object by the index of "parent" and "child". In this example the function enableMySelection will enable a selection depending on the number entered in the input. The function looks like this:
enableMySelection(parent_index, input_number) {
Object.keys(this.myDisableData[parent_index]).forEach(child_key => {
this.myDisableData[parent_index][child_key] = true;
});
this.myDisableData[parent_index][input_number] = false;
}
So if you enter "2" in your first input, it will enable the second selection of the first block. If you enter 1 in the second input, it will enable the first selection in the second block.
As I said, this is just a generally example but this should be enough to help you define the structure to handle your multiple inputs and selections.

How to change the value of a field in an array mongodb nodejs

There are many array levels, that's why I can't choose the right field, I guess.
This is the Schema of the model:
{
season: 1,
finished: 0,
Games: [{
Game: [{
game: 1,
Players: [{
Id: 0,
name: "Peter",
jails: 3, //I want to change this value
pays: 1000,
gets: 2000,
points: 3
}]
}]
}]
}
I tried this query but it's not working:
Seasons.update({
season: 1,
game: 2,
Id: 0
}, {
jails: 4
},
(err, data) => {
if (err) {
console.log(err)
} else {
console.log(data)
}
}
)
I have used the $set propery but it didn't work as I want. It make changes all jails field of all players to same value in the same season. I mean, the query is selecting the most parent record, so it is the season record. But I want to change value of child element.

Creating a Object with same Structure than received json

Hola Developers im trying to create a product in my shopping card , but still im stacked in one issue :
Can't find the proper way to design a object just on the same way i receive it from my json (back-end).
Lets say the part is causing the issue is this:
JSON RECEIVED
"product_category": [
{
"categories_of_product": "Good"
},
{
"categories_of_product": "Danger"
},
{
"categories_of_product": "Homer"
}
],
"people_buying_this_product": "Jack Ripper"
},
]
then on my building-product-processs , on the data return is a section that have to do with this, where in then using checkboxes i get which checkbox is checked or not , in order to build a array of categories similar to the former one i have shown:
DATA RETURN
ProductAdded: {
description: "",
upload_image3: "",
upload_image2: "",
upload_image1: "",
unities: 0,
price: 0,
name: "",
Categories: [
{ id: 1, value: "Miscellaneous", selected: false },
{ id: 2, value: "Homer", selected: false },
{ id: 3, value: "Electronic", selected: false },
{ id: 4, value: "Internet", selected: true },
{ id: 5, value: "Kids", selected: false },
{ id: 6, value: "Donas", selected: true },
{ id: 7, value: "Sports", selected: true },
{ id: 8, value: "Horror", selected: false }
],
METHOD that dispatches de action in vuex
addProductOnSale(thisCurrent) {
this.$store.dispatch("addProductSale", this.ProductAdded);
}
then being already in the VUEX state management , on the action in fact , trying to build the new product for this product category, i set this:
addProductSale({commit,getters},currentProduct){
product_category: currentProduct.Categories.filter(option =>
option.selected).map(option => {categories_of_product: option.value})
}
------------------->this one gives me undefined like:
"product_category":
[
undefined
],
"product_category":
[
undefined
],
"product_category":
[
undefined
],
]
or tried this other :
addProductSale({commit,getters},currentProduct){
product_category:currentProduct.Categories.forEach( option.selected,() =>
option.value).map(option => option.selected),...
}
and gave me error , not even showing a result.
Basically cant find the way to design the same structure im receiving for json , nor even reaching to values.
Is weird ,but if i only set the query like this:
addProductSale({commit,getters},currentProduct){
product_category:currentProduct.Categories.filter(option => option.selected)
}
Indeed filters and gives back the objects inside Categories which commit the condition of selected true , but with its plain format just as the data returns , but that's not the idea.
Any advice or help?
Thanks in advance!!!!

Vue.js updating a value upon deselecting a checkbox

Check out my fiddle:
https://jsfiddle.net/jqumt5oy/
I'm using a simple array to populate my table:
data: {
groceries: [
{ description: 'Chicken', price: 1, number: 4, selected: true },
{ description: 'Beef', price: 2, number: 0, selected: false },
{ description: 'Beer', price: 3, number: 2, selected: true },
{ description: 'Milk', price: 4, number: 0, selected: false }
]
},
How would I update the number of a row to zero when deselecting a checkbox? So when I want to leave something out of my list, I just have to deselect it, instead of first manually updating the number to 0?
I'm going to guess I would need a function for that, or can it be done easier by binding another v-model to the select menu for example?
Fixed it using a method:
<input type="checkbox" v-model="grocery.selected" #click="selectNumber(grocery)">
methods: {
selectNumber: function(grocery) {
if(grocery.selected == true)
{
grocery.number = 0;
grocery.selected = 0;
}
}
}
If anyone has a better solution, please feel free to post one.

Vue computed function resulting in error when data added

In my jsbin here http://jsbin.com/fecukitisu/edit?html,js,output. My total, and tax bindings are working until a user adds a new 'sale' via the included button. I cannot figure out why the computed functions return NAN when another sale is added. Any help is much appreciated!
It looks like an error with the return value of your component's data function. You have the "sale" property set to an array of objects. It should just be an object.
Change this:
data: function() {
return {
tip: 8.50,
sale: [
{ price: '' },
{ desc: '' },
{ amount: '' }
]
};
}
To this:
data: function() {
return {
tip: 8.50,
sale: {
price: '',
desc: '',
amount: ''
}
};
}

Categories

Resources