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
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
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:
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?
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
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.
Please or to participate in this conversation.