Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ivan2nn's avatar

$emit inside dynamic components

I am trying to build a form where the user can dynamically build groups of participants. I decided to tackle this problem letting the user generate a table for each group. Inside each table she/he could add and remove rows.

Until now I get to this point:

PARENT HTML:

<div class="form-group col-md-12 blocco-partecipante" v-for="participant_block in participant_blocks">    
  <mimi-table :operators='operators' :participant_block='participant_block' @removeBlockParticipant="removeBlockParticipant" @makeBlockWinner="makeBlockWinner"></mimi-table>   
</div>

STYLE.JS

Vue.component('mimi-table', {

props: ['operators', 'participant_block'],

template: '\
    <div>\
    <div class="row">\
        <div class="col-xs-6"><button type="button" class="btn btn-default" @click.prevent="makeBlockWinner">Winner</button></div>\
        <div class="col-xs-6"><button type="button" class="btn btn-danger pull-right" @click.prevent="removeBlockParticipant">Remove Block</button></div>\
    </div>\
    <table class="table table-bordered" id="participants-table" v-model="participant_block">\
        <thead>\
            <tr>\
                <th>#</th>\
                <th>Operator</th>\
                <th>Head Operator</th>\
                <th></th>\
            </tr>\
        </thead>\
        <tbody>\
            <tr v-for="(row, index) in rows" track-by="index">\
                <th>{{ index + 1 }}</th>\
                <td>\
                    <select style="width: 100%" v-model="row.selected">\
                        <option v-for="operator in operators" :selected="(row.selected == operator.name)">{{ operator.name}}</option>\
                    </select>\
                </td>\
                <td>\
                    <input type="checkbox" name="head" v-model="row.head_operator" @click="selectHeadOperator(index)"/>\
                </td>\
                <td>\
                    <input type="button" class="ibtnDel btn btn-md btn-danger" @click="removeOperator(index)" value="Remove" />\
                </td>\
            </tr>\
        </tbody>\
        <tfoot>\
            <tr>\
                <td colspan="4" style="text-align: left;">\
                    <input type="button" class="btn btn-lg btn-block" value="Add Operator to Participant Block" @click="addOperator"/>\
                </td>\
            <tr>\
            <tr>\
            </tr>\
        </tfoot>\
    </table>\
    </div>\
',

data: function () {
  return {
    rows : [
        
    ]
  }
}, 

methods: {
    addOperator: function() {
        this.rows.splice(this.rows.length, 0, {});
        if (this.rows.length == 1)
            this.rows[0].head_operator = true;
    },

    removeOperator: function(value) {
        this.rows.splice(value, 1);
    },

    selectHeadOperator: function(index) {
        this.rows.forEach(function(row, counter) {
            if (counter != index) row.head_operator = false;
        });
    },

    removeBlockParticipant: function() {
        this.$emit('removeBlockParticipant');
    },

    makeBlockWinner: function() {
        this.$emit('makeBlockWinner');
    }
}
});

new Vue({
el: '#main-form',

data: {
    participant_blocks: [],
    operators: [],
    index: 0
},

mounted: function() {
    vm = this;
    axios.get('/operators').then((response) => {
        vm.operators = response.data;
    });
}, 

methods: {
    addBlockParticipant: function() {
        this.participant_blocks.splice(this.participant_blocks.length, 0, {});
    },

    removeBlockParticipant: function() {
        console.log('test 1');
    },

    makeBlockWinner: function() {
        console.log('test 2');
    },
}
});

I have 3 questions about this approach:

  1. the $emit in the component does not fire the message to the parent. The removeBlockParticipant and makeBlockWinner they don't log the messages. I don't understand why. Is it because these components are created dynamically so I have to use another system?

  2. I would like that for each table if a row has the checkbox selected the other chckboxes of the same table deselect themselves. The method I implemented seems to show the changings only after i add and remove a row

  3. Form the design point of view (considering that I need to save the data of the forms) is it a good idea to think about an array of tables each one composed of an array of rows?

I would appreciate even just one answer to these questions.

Thank you.

0 likes
1 reply
ivan2nn's avatar

Ok I should have read that the attributes related to the events emitted by the child components should not have the camelCase systnax.

my fault

Please or to participate in this conversation.