Im using folowing code to render generic table:
<tr v-for="row in filteredData" >
<td v-for="column in visibleColumns">
<span v-if="column.type=='Date'" :class="column.cssClass">{{row[column.field] | formatDate}}</span>
<span v-else-if="column.type=='Bool'" :class="column.cssClass"><input #change="genericPost(column.url,row)" class="w3-check" type="checkbox" v-model="row[column.field]" ></span>
<span v-else-if="column.type=='Decimal'" :class="column.cssClass">{{row[column.field] | formatPrice}}</span>
<span v-else-if="column.type=='Button'" :class="column.cssClass"><a #click="clickItem(column.url,row)" class="w3-button w3-blue w3-padding-small">Edit</a></span>
<span v-else-if="column.type=='Link'" :class="column.cssClass"><router-link :to="{ path: row.route }">{{row[column.field]}}</router-link></span>
<span v-else :class="column.cssClass">{{row[column.field]}}</span>
</td>
</tr>
Is there any way to remove span element from conditional rendering ?
To have simple
<td class="xxx">value</td>
not <td><span class="xxx">value</span></td>
You can use v-for with child or sub <template> tags.
<tr v-for="row in filteredData" >
<td v-for="column in visibleColumns" :class="column.cssClass">
<template v-if="column.type=='Date'">{{row[column.field] | formatDate}}</template>
<template v-else-if="column.type=='Bool'" ><input #change="genericPost(column.url,row)" class="w3-check" type="checkbox" v-model="row[column.field]" ></template>
<template v-else-if="column.type=='Decimal'" {{row[column.field] | formatPrice}}</template>
<template v-else-if="column.type=='Button'" ><a #click="clickItem(column.url,row)" class="w3-button w3-blue w3-padding-small">Edit</a></template>
<template v-else-if="column.type=='Link'" ><router-link :to="{ path: row.route }">{{row[column.field]}}</router-link></template>
<template v-else >{{row[column.field]}}</template>
</td>
</tr>
In documentation: https://v2.vuejs.org/v2/guide/conditional.html#Conditional-Groups-with-v-if-on-lt-template-gt and https://v2.vuejs.org/v2/guide/list.html#v-for-on-a-lt-template-gt
FYI, it appears to be undocumented but it seems you can also use the <slot> tag in place of v-for with the <template> tags as well. Since I know there are no hidden "gotchas" with the template tag I just use it.
Related
I am using vuetify data table
<v-data-table
:headers="fields"
:items="items"
:search="search"
:mobile-breakpoint="NaN"
fixed-header
:loading="isBusy"
>
<template v-slot:item="{item,headers}">
<tr>
<td
v-for="(header, index) in headers"
:key="index"
>{{ header.formatFn(item[header.value]) }}</td>
</tr>
</template>
<template v-slot:item.userid="{ item }">Abc{{item}}</template>
<v-alert
slot="no-results"
:value="true"
color="error"
icon="warning"
>Your search for "{{ search }}" found no results.</v-alert>
<template slot="no-data">No Data Exists!</template>
</v-data-table>
The below slot template v-slot:item.userid="{ item }">Abc{{item}}</template> doesn't work for any reason which I am unable to figure out
My fields array has a field 'userid' present.
Well, it worked as I found a way through to it
<tr>
<td v-for="(header, index) in headers" :key="index">
<span
v-if="header.value != 'userid'"
>{{ header.formatFn(item[header.value]) }}</span>
<span v-else-if="header.value == 'userid'">
// do your work
</span>
<span v-else>{{ header.formatFn(item[header.value]) }}</span>
</td>
</tr>
Consider the following in a component snipet:
<tr v-for="row in rows" :key="row[rowKey]">
<td v-for="col in cols">
<slot v-if="col.bSlot" :name="col.bSlot" :row="row"></slot>
<template v-else v-html="formatField(row, col)"></template>
</td>
</tr>
Above I want to render a slot if given and if not to render a string returned by a formatting function unescaped. This did not work because I found out that v-html does not work with templates. The following works but you need extra unnecessary div tags that I don't want:
<td v-for="col in cols">
<slot v-if="col.bSlot" :name="col.bSlot" :row="row"></slot>
<div v-else v-html="formatField(row, col)"></div>
</td>
It would be nice if this still worked but has been deprecated:
<td v-for="col in cols">
<slot v-if="col.bSlot" :name="col.bSlot" :row="row"></slot>
<template v-else>
{{{formatField(row, col)}}}
</template>
</td>
The only other option I am left with is this but because there is no where to put the v-else I made the formatField() return nothing if a slot is given:
<td v-for="col in cols" v-html="formatField(row, col)">
<slot v-if="col.bSlot" :name="col.bSlot" :row="row"></slot>
</td>
formatField(row, col) {
if (col.bSlot) return; // also tried returning null, undefined, and ''
...
}
However now the slot doesn't render when one is provided. It seems like Vue ignores the slot if v-html is provided. So how do I not provide v-html when the col.bSlot is not provided?
You can place default value if slot is not given -
Fallback-Content
How about this:
1 <td v-for="col in cols">
2 <slot :name="col.bSlot" :row="row">
3 {{ formatField(row, col) }}
4 // <-- this is a comment
5 // <span v-html="formatField(row, col)"></span>
6 </slot>
7 </td>
I don't know how to add dynamic content in my Vue js 2 app. I'd like to add many div elements after clicking on a button. THis div should have input and after clicking on a Save button all input texts inside dynamically created divs should be sent to backend (so I use model inside my template).
<div v-if="!this.spinnerVisibleForCorrectiveActions">
<div>
<table class="p-2 table-cell">
<tr class="font-weight-bold">
<td class="vue-good-table-col-200">
<div class="mt-2 criterion">
ID
</div>
</td>
<td class="vue-good-table-col-200">
<div class="mt-2 criterion">
DZIAŁANIE
</div>
</td>
<td class="vue-good-table-col-200">
<div class="mt-2">
SZCZEGÓŁY
</div>
</td>
</tr>
<tr v-for="(actions,index) in correctiveActions" :key="index">
<td class="vue-good-table-col-200">
<span> {{actions.orderNumber}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.action}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.recommendations}}</span>
</td>
</tr>
</table>
<button class="addAction p-3 mb-2 bg-secondary text-white w-100 bg-info btn btn-success">NAdd new action</button>
<br>
</div>
How to add dynamically (multiple times) something like this and additionally to have the possibility to get all data from my dynamically created inputs after clicking on a button:
<tr v-for="(actions,index) in correctiveActions" :key="index">
<td class="vue-good-table-col-200">
<span> {{actions.orderNumber}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.action}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.recommendations}}</span>
</td>
</tr>
Ok, the answer in my case is very simple - I have to only add an empty object to my correctiveActions array:
<button class="addAction p-2 mb-2 bg-secondary text-white w-100 bg-info btn btn-success" #click="addNewAction">Nowe
działanie
</button>
and next:
methods:{
addNewAction() {
this.correctiveActions.push
({
id: undefined,
incidentId: this.incidentId,
orderNumber: this.getNextOrderNumber(),
action: undefined,
recommendations: undefined
});
},
}
I have a table where each "logical" row contains of two "markup rows".
<table class="table table-bordered">
<tbody>
<template v-for="(note, index) in notes">
<tr>
<td>
{{ moment(note.noteTime).format('YYYY-MM-DD HH:mm') }}
</td>
<td>
{{ note.locationName }}
</td>
</tr>
<tr>
<td colspan="2">
{{ note.noteText }}
</td>
</tr>
</template>
</tbody>
</table>
Is there a way generate this kind of table in vue without hurting html syntax (template element is not valid inside tbody)?
<template> does not generate a html element and thus will not interfere with html syntax.
There is actually a similar example inside the VueJS docs:
https://v2.vuejs.org/v2/guide/list.html#v-for-on-a-lt-template-gt
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
Here is a jsFiddle to see the example from the docs in action. You can inspect the HTML syntax:
https://jsfiddle.net/50wL7mdz/545901/
I am trying to add a collapse component from bootstrap-vue into a table I am creating (Not bootstrap-vue table as find it easier to use plain table)
Can anyone tell me why this works as expected (But obviously opens every collapse component with the same ID)
<td>
<fa icon="bars" v-b-toggle.collapse2/>
</td>
</tr>
<td colspan="4">
<b-collapse id="collapse2" >
<b-card>
<p class="card-text">Collapse contents Here</p>
</b-card>
</b-collapse>
</td>
But this doesn't work, I know i have a unique id in case.id
<td>
<fa icon="bars" v-b-toggle="'collapse-' + case.id" />
</td>
</tr>
<td colspan="4">
<b-collapse id="'collapse-' + case.id" >
<b-card>
<p class="card-text">Collapse contents Here</p>
</b-card>
</b-collapse>
</td>
Many Thanks
You are not setting up a proper attribute binding in id="'collapse-' + case.id". It works in v-b-toggle="'collapse-' + case.id" case because as stated in the docs
Directive attribute values are expected to be binding expressions
In case of attributes you should use one of the following:
mustache
<div id="item-{{ id }}"></div>
v-bind
<div v-bind:id="'item-' + id"></div>
shorthand :
<div :id="'item-' + id"></div>