0
votes

I am currently trying to have a child component $emit data into an object of a parent, and the parent object is included in an array that is created and added to when clicking a button.

one iteration of create component button one iteration of create component button

clicking the button twice, adds 2 more objects into the array clicking the button twice, adds 2 more objects into the array

I do not understand how I can add numbers into amountbudgeted via props and emits while also creating new components.

New to Vue so sorry if it is not the best description

array of objects array of objects

each object in the area has an amountbudgeted, uniqueid, remaining, input budget each object in the area has an amountbudgeted, uniqueid, remaining, input budget

Parent Component

<div class="budgetItemContainer">
        <div class="budgetItemRow">
            <!--component being created via button click-->
            <div v-for="(input, index) in budgetRows" :key="index">

            <!--<component :is="$options.components.budgetItemRowContent" v-bind="budgetRows"></component>-->
                <budgetItemRowContent v-bind:="budgetRows" ></budgetItemRowContent>
            <progress data-min="0" data-max="100" data-value="20"></progress>
            </div>
        </div>
    </div>

export default {
name: 'budgetGroup',
components: {
    budgetItemRowContent,
    BudgetItemButton,
},
data: () => {
    return {
        budgetItemHeading: 'Housing',
        budgetRows: [
            {
                inputbudget: '',
                amountbudgeted: 0,
                remaining: 0,
                id: uniqId(),
            },
        ],
    };
},
methods: {
    //creates new budgetRow when button is clicked
    createNewContent() {
        this.budgetRows.push({inputbudget: '', amountbudgeted: 0, remaining: 0, id: uniqId() });
    },
},
}


Child Component

 <!--input that will hopefully update amoundbudgeted in parent object-->


       <div class="budgetItemRow-Column">
        <div class="budgetItemLabel">
            <input v-model="blabel" type="text" maxlength="32" placeholder="Label" class="input-Budget-Inline-Small budgetItemRow-Input">
        </div>
    </div>

    <!--input that will hopefully update amoundbudgeted in parent object-->
    <div class="budgetItemRow-Column">
        <div class="amountBudgetedInputContainer">
            <input v-model.number="amount" class="amountBudgetedNumber budgetItemRow-Input input-Budget-Inline-Small" type="number" placeholder="$">
        </div>
    </div>

     export default {
    props: ['value', 'label'],
    computed: {
        amount: {
            set(newVal) {
                this.$emit('input', newVal);
            },
            get() {
                return this.value;
            },
        },
        blabel : {
            set(newLab) {
                this.$emit('labels', newLab);
            },
            get() {
                return this.label;
            }
        }
    },
};
1

1 Answers

2
votes

If you're just concerned with amountBudgeted then here's how you would lay out your code.

First, convert the component line to the following:

//<component :is="$options.components.budgetItemRowContent" v-bind="budgetRows"></component>
<budgetItemRowContent v-model="budgetRows[index].amountBudgeted"></budgetItemRowContent>

This basically just makes your code cleaner and readable. Note that I've also attached a v-model to the component, this is basically the same as a) passing a value prop and b) watching an input event and then updating the binding (in this case, budgetRows[index].amountBudgeted) with the payload of the event.

Next, change your child component to the following:

...
<input v-model.number="amount" ...
...

<script>
export default {
  // Name isn't 100% necessary here as it's inferred from the parent scope
  props: ['value'], //Implicitly passed from parent
  computed: {
    amount: {
      set(newVal){
        this.$emit('input', newVal)
      },
      get(){
        return this.value
      },
    },
  }
}
</script>

This should get you on the right track, let me know if you have any issues.