My template
<div class="form-group">
<p class="required">4. How did you hear about our distribution?</p>
<p id="skip">Check all that apply</p>
<b-form-checkbox v-for="item in choices" :key="item" :value="item" v-model="socialMedia" required> {{ item }} </b-form-checkbox>
<b-form-checkbox v-on:click="onclick"> Other: </b-form-checkbox>
<input type="text" class="form-control" :disabled='isDisabled' v-model="other">
<button name="btn" v-show="!isDisabled" #click="addType" required>+</button>
<span class="mt-3">Selected: <strong>{{ socialMedia }}</strong></span>
<br>
<span class="mt-3">Additional check: <strong>{{ other }}</strong> <br><label id="small">Do NOT forget to click PLUS button for optional</label></span>
</div>
My Vue Instance:
export default {
data() {
return {
selected: [],
choices: ['Facebook', 'Instagram', 'Twitter', 'Word of Mouth', 'KMAZ 102.5fm'],
isDisabled: true,
other: '',
}
},
methods: {
onclick() {
this.isDisabled = !this.isDisabled
if (this.selected.length) {
this.selected = this.selected.filter(s => s !== this.other)
}
this.other = ''
},
addType() {
this.socialMedia.push(this.other)
}
}
}
This Vue project will create a checkbox list that allows users to add multiple values and optional. For example, Other box is checked and no values are entered, then click + button, this will add an empty string to the array.
I was trying to do like below, but it did not work:
<div class="form-group">
<p class="required">4. How did you hear about our distribution?</p>
<p id="skip">Check all that apply</p>
<b-form-checkbox v-for="item in choices" :key="item" :value="item" v-model="socialMedia" #change="DetectedEmptyString()"required> {{ item }} </b-form-checkbox>
<b-form-checkbox v-on:click="onclick"> Other: </b-form-checkbox>
<input type="text" class="form-control" :disabled='isDisabled' v-model="other">
<button name="btn" v-show="!isDisabled" #click="addType" required>+</button>
<span class="mt-3">Selected: <strong>{{ socialMedia }}</strong></span>
<br>
<span class="mt-3">Additional check: <strong>{{ other }}</strong> <br><label id="small">Do NOT forget to click PLUS button for optional</label></span>
</div>
export default {
data() {
return {
selected: [],
choices: ['Facebook', 'Instagram', 'Twitter', 'Word of Mouth', 'KMAZ 102.5fm'],
isDisabled: true,
other: '',
}
},
methods: {
onclick() {
this.isDisabled = !this.isDisabled
if (this.selected.length) {
this.selected = this.selected.filter(s => s !== this.other)
}
this.other = ''
},
addType() {
this.socialMedia.push(this.other)
},
DetectedEmptyString() {
return this.socialMedia.filter(x => x !== "")
}
}
}
Expected Output: No matter how many times I click + button, the empty string is automatically removed.
Related
I have dynamic generated form in Vue. Every loop have v-model. Everything work fine. But when I use checkboxes v-model work for all loops not on one like in input type text. Can You help me solved this problem? Below Vue code:
<fieldset>
<div class="form-row mb-2" v-for="input, index in journal" :key="index">
<div class="col-auto">
<label for="date">Data</label>
<Datepicker v-model="input.date" input-class="form-control" :input-attr="{id: 'date', name: 'date'}" style="width: 100%;" />
</div>
<div class="col-md-2">
<label for="timeStart">Od</label>
<Datepicker type="time" v-model="input.timeStart" format="HH:mm" input-class="form-control" :input-attr="{id: 'timeStart', name: 'timeStart'}" style="width: 100%;" />
</div>
<div class="col-md-2">
<label for="timeEnd">Do</label>
<Datepicker type="time" v-model="input.timeEnd" format="HH:mm" input-class="form-control" :input-attr="{id: 'timeEnd', name: 'timeEnd'}" style="width: 100%;" />
</div>
<div class="col-md-2">
<label for="players">Lista obecności</label>
<div class="form-check" v-for="item in input.players">
<input v-model="item.checked" type="checkbox" class="form-check-input" :id="'id-'+item.id+'set'+index">
<label class="form-check-label" :for="'id-'+item.id+'set'+index">{{ item.fullName }}</label>
</div>
</div>
<div class="col-auto">
<label for="description">Opis</label>
<textarea v-model="input.description" class="form-control" rows="7" id="description" placeholder="Opis"></textarea>
</div>
<div class="col-auto" #click="addInput" v-show="index == journal.length-1 && journal.length < 16">
<ButtonVue style="margin-top: 30px;" title="Dodaj" type="button" cancelWidth="true" color="btn-success"><i class="fas fa-plus"></i></ButtonVue>
</div>
<div class="col-auto align-self-start" #click="removeInput(index)" v-show="index || ( !index && journal.length > 1)">
<ButtonVue style="margin-top: 30px;" title="Usuń" type="button" cancelWidth="true" color="btn-danger"><i class="fas fa-minus"></i></ButtonVue>
</div>
</div>
</fieldset>
data() {
return {
contact: [],
journal: [{
date: "",
timeStart: "",
timeEnd: "",
players: "",
description: ""
}],
contacts: [],
}
},
Methods:
Method for creating dynamic form
addInput() {
this.journal.push({
date: "",
timeStart: "",
timeEnd: "",
players: this.contact,
description: ""
});
},
And here is the method which gets players from contacts
getContacts() {
this.pageLoader = true;
this.$http.get('/pkpar/get-contacts')
.then(({
data
}) => {
this.contacts = data.contacts;
for(let i=0; i<this.contacts.length; i++)
{
this.contact.push({'id': this.contacts[i]['id'], 'fullName' :
this.contacts[i]['fullName'], 'checked': true});
}
this.journal[0].players = this.contact;
this.pageLoader = false;
})
.catch(error => {
console.log(error);
});
},
Your addInput method creates and pushes new object into journal array, but each object created this way has a players property which references same array (this.contact)
The Difference Between Values and References in JavaScript
Easiest (but not most optimal) way to handle this is to create a copy of the array and objects inside for each new journal:
addInput() {
this.journal.push({
date: "",
timeStart: "",
timeEnd: "",
players: this.contact.map((player) => ({ ...player })),
description: ""
});
},
I'm trying to append new input fields based on a condition, I will describe the workflow to help you understand
First stage is to press this button to implement 2 functions(1 is to move to other fieldset in the staged form, second function is to append the inputs:
<input type="button" name="secondBtn" class="next action-button" value="Next" id="secondBtn" #click="nextPlusappend"/>
nextPlusappend:
nextPlusappend() {
this.isNextClicked();
this.appendFields();
}
appendFields:
//this.platform initllized as 'one' so the condition is true.
if(this.platform === 'one'){
this.inputFields.push({
Username: '',
Password: '',
AffiliateID: '',
CI: '',
GI: '',
})
}
And I want to append all the fields from the function to this fieldset:
<div v-if="currentPage === 2">
<fieldset id="fieldset3" v-for="(param, index) in inputFields" :key="index">
<h2 class="fs-title">API Credentials</h2>
<h3 class="fs-subtitle">Step 3- Add any parameter for the integration</h3>
<input v-model="param.Username" type="text" name="`inputFields[${index}[Username]]`" placeholder="userName">
<input type="button" name="previous" class="previous action-button" value="Previous" #click="isPreviousClicked"/>
<input type="submit" name="submit" class="submit action-button" value="Create a Ticket" id="excel"/>
</fieldset>
</div>
How can I append this without hard code all the input fields as I did here:?
<input v-model="param.Username" type="text" name="`inputFields[${index}[Username]]`" placeholder="userName">
This is designated to be dynamic, what do i mean?
I mean that if the this.platform is equal to "one" there will be a unique fields, and if this.platform equal to "two" for example there will be other unique fields.
Don't think like "pushing a form field", rather think like "adding a new item to the dataset" (and of course, its displayed UI is a form field).
Let me give an example:
Vue.component("FormField", {
props: ["label", "value"],
computed: {
val: {
get() {
return this.value
},
set(val) {
this.$emit("update:value", val)
}
},
},
methods: {
handleClickAdd() {
this.$emit("click-add-field")
}
},
template: `
<div>
<label>
{{ label }}: <input type="text" v-model="val" />
</label>
<button
#click="handleClickAdd"
>
+ ADD
</button>
</div>
`,
})
new Vue({
el: "#app",
data() {
return {
formFields: [{
label: "Field 1",
value: null,
}],
}
},
methods: {
handleClickAddField() {
const item = {
label: `Field ${ this.formFields.length + 1 }`,
value: null,
}
this.formFields = [...this.formFields, item]
},
},
template: `
<div
class="container"
>
<div
class="col"
>
<h4>FIELDS:</h4>
<hr>
<form-field
v-for="(field, i) in formFields"
:key="i"
:label="field.label"
:value.sync="field.value"
#click-add-field="handleClickAddField"
/>
</div>
<div
class="col"
>
<h4>FIELD VALUES:</h4>
<hr>
<div
v-for="(field, i) in formFields"
:key="i"
>{{ field.label }}: {{ field.value }}</div>
</div>
</div>
`,
})
.container {
display: flex;
}
.col {
padding: 0 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
You can see, that on ADD I just added a new item in the formFields - the values are bound in the template to a child-component, that handles the actual representation of the fields.
On the right side of the snippet, you can see another benefit of decoupling data from UI: I created another representation of the same data source - that immediately reacts to any changes!
I have a list with comments, those comments have a moment field, which is a DateTimeField. In this DateTimeField I have for example this --> 2020-06-03T15:32:01.803027 and I want to delete that T character, or replace with a blank space.
I'm using Django for the backend and Vue.js for the frontend.
I was able to remove the Z character by changing the USE_TZ = True to False option in the settings.py file. But I can't remove the T character, that's all I need. I have tried from the frontend to remove the T character using methods and computed properties, but I can't use the replace("T", " ") method on a DateTimeField, I can only use it on a String
<template lang="html">
<div class="container">
<div class="row">
<div class="col text-left">
<h2>Detalles del partido</h2>
</div>
</div>
<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<form>
<form #submit="onSubmit">
<div class="form-group row">
<label for="nombreLocal" class="col-sm-2 col-form-label">Local</label>
<div class="col-sm-6">
<input type="text" name="nombreLocal" class="form-control" readonly v-model.trim="form.nombreLocal">
</div>
</div>
<div class="form-group row">
<label for="nombreVisitante" class="col-sm-2 col-form-label">Visitante</label>
<div class="col-sm-6">
<input type="text" name="nombreVisitante" class="form-control" readonly v-model.trim="form.nombreVisitante">
</div>
</div>
<div class="form-group row">
<label for="resultado" class="col-sm-2 col-form-label">Resultado</label>
<div class="col-sm-6">
<input type="text" name="resultado" class="form-control" readonly v-model.trim="form.resultado">
</div>
</div>
<div class="form-group row">
<label for="pronosticoSistema" class="col-sm-2 col-form-label">Pronóstico del sistema</label>
<div class="col-sm-6">
<input type="text" name="pronosticoSistema" class="form-control" readonly v-model.trim="form.pronosticoSistema">
</div>
</div>
<div class="form-group row">
<label for="premio" class="col-sm-2 col-form-label">Premio</label>
<div class="col-sm-6">
<input type="number" name="premio" class="form-control" readonly v-model.trim="form.premio">
</div>
</div>
<div class="form-group row">
<label for="dificultad" class="col-sm-2 col-form-label">Dificultad</label>
<div class="col-sm-6">
<input type="text" name="dificultad" class="form-control" readonly v-model.trim="form.dificultad">
</div>
</div>
<div class="rows">
<div class="col text-left">
<b-button size="sm" variant="primary" :to="{ name:'CreatePronostico', params: {partidoId: this.partidoId} }">
Pronosticar
</b-button>
<b-button size="sm" variant="primary" :to="{ name:'CreateComentario', params: {partidoId: this.partidoId}}">
Comentar
</b-button>
<b-button size="sm" type="submit" class="btn-large-space" :to="{ name: 'PronosticadorUsuario'}">Atrás</b-button>
</div>
</div>
</form>
<br>
<h2>Comentarios</h2>
<br>
<div class="comentarios">
<b-table striped hover
:items="comentarios"
:fields="fields"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc">
<template v-slot:cell(action)="data">
<b-button size="sm" variant="primary" :to="{ name:'CreateComentarioRespuesta', params: {comentarioId: data.item.id} }">
Responder
</b-button>
<b-button size="sm" variant="primary" :to="{ name:'DarMeGusta', params: {comentarioId: data.item.id} }">
Me gusta
</b-button>
<b-button size="sm" variant="primary" :to="{ name:'EditComentario', params: {comentarioId: data.item.id} }">
Editar
</b-button>
<b-button size="sm" variant="danger" :to="{ name:'DeleteComentario', params: {comentarioId: data.item.id} }">
Eliminar
</b-button>
</template>
</b-table>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import swal from 'sweetalert'
import router from "../../router";
export default {
mounted() {
this.checkLoggedIn();
},
data() {
return {
sortBy: 'momento',
sortDesc: false,
partidoId: this.$route.params.partidoId,
form: {
nombreLocal: '',
nombreVisitante: '',
resultado: '',
pronosticoSistema: '',
premio: '',
dificultad: ''
},
fields: [
{ key: 'id', label: 'Número de comentario' },
{ key: 'momento', label: 'Momento', sortable: true},
{ key: 'texto', label: 'Texto' },
{ key: 'meGustas', label: 'Número de "me gustas"', sortable: true},
{ key: 'autor', label: 'Autor' },
{ key: 'comentarioRespuesta', label: 'Responde a' },
{ key: 'action', label: '' }
],
comentarios: []
}
},
methods: {
checkLoggedIn() {
this.$session.start();
if (!this.$session.has("token")) {
router.push("/auth");
}
},
onSubmit(evt){
evt.preventDefault()
const path = `http://localhost:8000/api/v1.0/partidos/${this.partidoId}/`
axios.get(path, this.form).then((response) =>{
this.form.nombreLocal = response.data.nombreLocal
this.form.nombreVisitante = response.data.nombreVisitante
this.form.resultado = response.data.resultado
this.form.pronosticoSistema = response.data.pronosticoSistema
this.form.premio = response.data.premio
this.form.dificultad = response.data.dificultad
})
.catch((error) => {
console.log(error)
})
},
getPartido (){
const path = `http://localhost:8000/api/v1.0/partidos/${this.partidoId}/`
axios.get(path).then((response) =>{
this.form.nombreLocal = response.data.nombreLocal
this.form.nombreVisitante = response.data.nombreVisitante
this.form.resultado = response.data.resultado
this.form.pronosticoSistema = response.data.pronosticoSistema
this.form.premio = response.data.premio
this.form.dificultad = response.data.dificultad
})
.catch((error) => {
console.log(error)
})
},
getComentarios (){
const path = 'http://localhost:8000/api/v1.0/comentarios/'
axios.get(path).then((response) => {
this.comentarios = response.data
})
.catch((error) => {
console.log(error)
})
},
},
computed: {
comentariosFormateados: function (){
var res = [];
for(var i = 0; i < this.comentarios.length; i++){
this.comentarios[i].momento.toISOString().replace('T', '');
res.push(comentarios[i]);
}
return res;
}
},
created() {
this.getPartido(),
this.getComentarios()
}
}
</script>>
<style lang="css" scoped>
</style>
Just return the Django DateTime object formatted however you want, for example:
myDateTime = strftime(MyModel.objects.get(id=id).moment, "%Y-%m-%d %H:%M:%S.%f")
Or:
comment = MyModel.objects.get(id=id)
moment = strftime(comment.moment, "%Y-%m-%d %H:%M:%S.%f")
comment.formatted_moment = moment
...
Then return it to your view in that format (a formatted string).
I've solved with this:
formatMomento(value) { const formattedDate = DateTime.fromISO(value).toLocaleString(DateTime.DATETIME_SHORT); return formattedDate; },
And calling it from the formatter attribute:
fields: [
{ key: 'id', label: 'Número de comentario' },
{ key: 'momento', formatter: "formatMomento", label: 'Momento', sortable: true},
{ key: 'texto', label: 'Texto' },
{ key: 'meGustas', label: 'Número de "me gustas"', sortable: true},
{ key: 'autor', formatter: "nombreDeUsuario", label: 'Autor' },
{ key: 'comentarioRespuesta', label: 'Responde al comentario:' },
{ key: 'action', label: '' }
],
I am attempting to add objects into an array I declared in Vue instance data object. I can set the values in the state's purchase object, but when I push data into the orders queue array, the empty array is not populated. The function is being triggered, but the array does not update.
Here is my form:
<form
v-on:submit.prevent="queuePurchase"
class="form-inline row"
id="order-creation-form"
method="POST"
>
#csrf
<autocomplete-field
sizing="col-xs-12 col-sm-3 col-md-3"
name="customer"
label="Customer"
:data="{{ json_encode($customers) }}"
v-on:setcustomer="setCustomer($event)"
></autocomplete-field>
<div class="col-xs-12 col-sm-3 col-md3 form-group d-flex flex-column align-items-start">
<label for="phone">Product</label>
<select
v-model="purchase.product"
class="form-control w-100"
name="product"
aria-describedby="productHelpBlock"
required
>
#foreach ($products as $product)
<option :value="{{ json_encode($product) }}">
{{ $product->name }}
</option>
#endforeach
</select>
<small id="productHelpBlock" class="form-text text-muted">
Select a product
</small>
</div>
<div class="col-xs-12 col-sm-3 col-md-3 form-group d-flex flex-column align-items-start">
<label for="phone">Quantity</label>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
class="form-control w-100"
aria-describedby="productHelpBlock"
required
>
<small id="productHelpBlock" class="form-text text-muted">
Product quantity
</small>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success icon-button d-flex">
<i class="material-icons">add</i>
<span> Q U E U E</span>
</button>
</div>
</form>
And here is my javascript:
require("./bootstrap");
window.Vue = require("vue");
Vue.component("queue-table", require('./components/QueueTable.vue'));
Vue.component("autocomplete-field", require('./components/AutocompleteField.vue'));
const purchaseApp = new Vue({
el: "#purchase-app",
data() {
return {
queue: [],
purchase: {
product: null,
customer: null,
quantity: null
}
}
},
methods: {
setCustomer: function(customerObj) {
this.purchase.customer = customerObj;
},
queuePurchase: function() {
this.queue.push( this.purchase );
}
}
});
Could someone please explain what & why it is happening?
The push() method ought to add purchase objects to the queue array, but as #FK82 pointed out in his comment, push() is adding multiple references to the same purchase object. This means that if you change the object by increasing the quantity, every purchase's quantity property will be updated.
You can give that a try here:
const exampleComponent = Vue.component("example-component", {
name: "exampleComponent",
template: "#example-component",
data() {
return {
queue: [],
purchase: {
product: null,
customer: null,
quantity: null
}
};
},
methods: {
queuePurchase() {
this.queue.push( this.purchase );
}
}
});
const page = new Vue({
name: "page",
el: ".page",
components: {
"example-component": exampleComponent
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<template id="example-component">
<div>
<p>The Queue has {{ this.queue.length }} items.</p>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
placeholder="Quantity"
>
<button #click="queuePurchase">
Add to Queue
</button>
<pre>{{ JSON.stringify(this.queue, null, 2) }}</pre>
</div>
</template>
<div class="page">
<example-component></example-component>
</div>
Instead of push()ing a reference to the same purchase object, try creating a shallow copy with Object.assign({}, this.purchase) or by using the spread operator. Here's an example that uses the spread operator and then push()es the copy onto the queue:
const exampleComponent = Vue.component("example-component", {
name: "exampleComponent",
template: "#example-component",
data() {
return {
queue: [],
purchase: {
product: null,
customer: null,
quantity: null
}
};
},
methods: {
queuePurchase() {
this.queue.push({...this.purchase});
}
}
});
const page = new Vue({
name: "page",
el: ".page",
components: {
"example-component": exampleComponent
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<template id="example-component">
<div>
<p>The Queue has {{ this.queue.length }} items.</p>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
placeholder="Quantity"
>
<button #click="queuePurchase">
Add to Queue
</button>
<pre>{{ JSON.stringify(this.queue, null, 2) }}</pre>
</div>
</template>
<div class="page">
<example-component></example-component>
</div>
I'm trying to add a class to a parent container each time an "advanced" link is clicked.
So with jQuery I would just write something like..
$(this).closest('.row').addClass('overlay');
or
$(this).closest('section').addClass('overlay');
But it seems to be getting a little complex with Vue to just add a class to the parent container of the item that is clicked. I'm sure there is a more simple way to go about it.
Here is an example of my code.
<div id="app">
<section v-bind:class="{ overlay: i == sectionActive && rowActive == null }" v-for="(section, i) in sections">
Advanced
<div class="advanced-fields" v-bind:class="{ overlay: i == sectionActive && rowActive == null }">
<fieldset>
<label>
ID
<input type="text" name="section[id]" v-model="section.id">
</label>
</fieldset>
<fieldset>
<label>
Class
<input type="text" name="section[css_class]" v-model="section.css_class">
</label>
</fieldset>
</div>
<div class="row" v-bind:class="{ overlay: i == sectionActive && row_i == rowActive }" v-for="(row, row_i) in section.rows">
Advanced
<div class="advanced-fields" v-bind:class="{ overlay: i == sectionActive && row_i == rowActive }">
<fieldset>
<label>ID</label>
<input type="text" name="" v-model="row.id">
</fieldset>
<fieldset>
<label>CSS Class</label>
<input type="text" name="" v-model="row.css_class">
</fieldset>
</div>
</div>
</section>
<pre>{{ $data }}</pre>
</div>
<script>
new Vue({
el: "#app",
data: {
"sections": [{
"id": "section-1",
"css_class": "",
"rows": [{
"id": "",
"css_class": ""
}, {
"id": "",
"css_class": ""
}]
}, {
"id": "section-2",
"css_class": '',
"rows": [{
"id": "",
"css_class": ""
}]
}],
sectionActive: null,
rowActive: null,
columnActive: null
},
methods: {
toggleAdvanced: function(index) {
this.sectionActive = this.sectionActive === index ? null : index;
this.rowActive = null;
this.columnActive = null;
},
toggleRowAdvanced: function(section, row) {
var sectionIndex = this.sections.indexOf(section);
var rowIndex = section.rows.indexOf(row);
this.sectionActive = this.sectionActive === sectionIndex ? null : sectionIndex;
this.rowActive = this.rowActive === rowIndex ? null : rowIndex;
}
}
});
</script>
I need to do the same thing for columns but as you can see, it is getting too overly complicated. Any ideas on how to simplify this?
I know it would be easier to add a data attribute to each row, but I am saving the hash to a database and don't want to add in unnecessary data just for a UI toggle.
https://jsfiddle.net/ferne97/4jbutbkz/
I took a different approach and built several re-usable components. This removes all the complicated logic that you are putting into your Vue.
Vue.component("expand-link",{
template:`Advanced`,
data(){
return {
expanded: false
}
},
methods:{
toggle(){
this.expanded = !this.expanded
this.$emit('toggled', this.expanded)
}
}
})
Vue.component("expanded-fields",{
props:["details", "expanded"],
template:`
<div class="advanced-fields" :class="{overlay: expanded}">
<fieldset>
<label>
ID
<input type="text" name="section[id]" v-model="details.id">
</label>
</fieldset>
<fieldset>
<label>
Class
<input type="text" name="section[css_class]" v-model="details.css_class">
</label>
</fieldset>
</div>
`
})
Vue.component("expandable-section", {
props:["section"],
template:`
<section>
<expand-link #toggled="onToggle"></expand-link>
<expanded-fields :details="section" :expanded="expanded"></expanded-fields>
<expandable-row v-for="row in section.rows" :key="row" :row="row"></expandable-row>
</section>
`,
data(){
return {
expanded: false
}
},
methods:{
onToggle(val){
this.expanded = val
}
}
})
Vue.component("expandable-row",{
props:["row"],
template:`
<div class="row">
<h3>Row</h3>
<expand-link #toggled="onToggle"></expand-link>
<expanded-fields :details="row" :expanded="expanded"></expanded-fields>
</div>
`,
data(){
return {
expanded: false
}
},
methods:{
onToggle(val){
this.expanded = val
}
}
})
And the template simply becomes
<div id="app">
<expandable-section v-for="section in sections" :key="section" :section="section"></expandable-section>
<pre>{{ $data }}</pre>
</div>
Here is your fiddle updated.