Как отправить модальные данные родителю в Bootstrap Vue?

Я новичок в Vue и Bootstrap Vue.

Я построил таблицу, которая использует массив данных API. В этой таблице есть кнопка, которая открывает <b-modal> в дочернем компоненте. В модальном окне есть три поля, которые добавляют данные в массив таблицы нажатием кнопки. Затем таблица обновляется. Пока здесь все в порядке.

Проблема в том, что когда я пытаюсь отправить больше информации из <b-modal>, информация, которую я добавил ранее из <b-modal>, изменяется — как в массиве, так и в таблице. Информация, полученная из API, не была изменена.

Что не так? Большое спасибо.

Vue.component('modal', {
    props:['commodity_data'],
    template:/*html*/`
        <div>            
            <b-modal id = "addModal" ref = "modal" hide-footer title = "Add Commodity">
                <b-form-group>
                    <label>
                    Hu Count
                        <b-form-input
                            id = "hu_count"
                            v-model = "new_row.hu_count"
                            >
                        </b-form-input>
                    </label>
                    <label>
                    Dimensions
                        <b-form-input
                            id = "dimensions"
                            v-model = "new_row.dimensions"
                            >
                        </b-form-input>
                    </label>
                    <label>
                    Weight
                        <b-form-input
                            id = "weight"
                            v-model = "new_row.weight"
                            >
                        </b-form-input>
                    </label>
                </b-form-group>

            <b-button variant = "success" @click = "addRow">Add Row</b-button> 
        </b-modal>

        </div>
    `,
    data(){
        return{
            new_row:
            {
                dimensions: '',
                hu_count: '',
                weight: '',
            }
        }
    },
    methods:{
        addRow: function () {            
            this.commodity_data.push(this.new_row)
            this.$refs.modal.hide()
            console.info(this.commodity_data);
        }
    }
})

Код таблицы, содержащей b-модальность:

Vue.component('commodity', {
    template: /*html*/`
    <div class = "mx-auto commodity card">
            <div class = "commodity__div-buttons">
                <div class = "commodity__buttons">
                    <b-button variant = "success" v-b-modal.addModal>Add Row</b-button> 
                    <b-button variant = "danger" @click = "deleteRows">Delete</b-button> 
                </div>
            </div>

        <b-table striped hover responsive :fields = "fields" :items = "commodity_data">

            <template #head(index) = "data">
                <input type = "checkbox" @click = "selectAll" ref = "checkAll">
            </template>

            <template #cell(index) = "data">        
                <input type = "checkbox" @click = "selectRows(data.index)">
            </template> 

        </b-table>

        <modal id = "addModal" :commodity_data = "commodity_data"></modal>
        
    </div>
    `,
    data() {
        return {
            commodity_data: [],
            checkboxes: '',
            fields: [
                {
                    key: 'index'
                },
                {
                    key: 'hu_count',
                    label: 'Hu Count'
                },
                {
                    key: 'dimensions',
                    label: 'Dimensions'
                },
                {
                    key: 'weight',
                    label: 'Weight'
                }
            ]
        }
    },
    methods: {
        selectRows: function (e) {
            this.commodity_data[e].checked = !this.commodity_data[e].checked
        },
        deleteRows: function () {
            for (let i = 0; i < this.commodity_data.length; i++) {
                if (this.commodity_data[i].checked) {
                    this.commodity_data.splice(i, 1)
                    i--
                }
            }
            this.checkboxes.forEach(element => {
                element.checked = false
            });
        },
        selectAll: function () {
            this.commodity_data.forEach(element => {
                element.checked = !element.checked
            });

            if (this.$refs.checkAll.checked) {
                this.checkboxes.forEach(element => {
                    element.checked = true
                });
            } else {
                this.checkboxes.forEach(element => {
                    element.checked = false
                });
            }
        }
    },
    created: function () {
        let data = JSON.parse(sessionStorage.getItem('data_info'))
        this.commodity_data = data.commodity
        
    },
    mounted(){
        const table = document.querySelector('table')
        this.checkboxes = table.querySelectorAll('input')
    }
})
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 292
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть две проблемы: 1) мы не должны никогда не изменять свойства в дочернем компоненте, 2) при добавлении данных вы каждый раз добавляете одну и ту же ссылку на дочерние данные.

Фиксация ребенка

Вместо изменения реквизита $emit событие с клонированными дочерними данными:

addRow() {
   this.$emit('add', { ...this.new_row });  
   this.$refs.modal.hide()
}

The spread operator creates a shallow copy.

Фиксация родителя

Теперь дочерний элемент генерирует событие, которое должен прослушивать родитель. Создайте прослушиватель для дочернего тега:

<modal id = "addModal" @add = "addData" :commodity_data = "commodity_data"></modal>

И создайте метод обработчика (в родительском):

addData(data) {
   this.commodity_data.push(data);
}

Другие вопросы по теме