Как сделать элемент <tr> в vuejs, который содержит <slot> с html

106
12

Я хотел бы сделать компонент строки таблицы, который может содержать слот, в котором есть HTML. Проблема в том, что браузер выводит текст из таблицы до того, как vuejs сможет его отобразить.

Например, я хотел бы сделать такую таблицу https://codepen.io/mankowitz/pen/LqLRWr

td, th {
border: 1px solid red;
}

.main-table {
border: 2px solid blue;
}

<table class="main-table">
<thead>
<tr>
<th>Col1</th>
<th>Col2</th>
<th>Col3</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3">Collapsed row</td>
</tr>
<tr>
<td>
<p>text</p>
<table>
<tr>
<th>embedded table header</th>
</tr>
<tr>
<td>embedded table text</td>
</tr>
</table>
</td>
<td> Col2 </td>
<td> Col3 </td>
</tr>
<tr>
<td>
regular row col1</td>
<td>col2</td>
<td>col3</td>
</tr>
</table>

Тем не менее, когда я помещаю его в шаблон VUE, форматирование все неправильно. Смотрите https://codepen.io/mankowitz/pen/PVmBxV

Vue.component("table-row", {
props: ["collapsed"],
template: '
<tr>
<td v-if="collapsed" colspan="3">collapsed row</td>
<td v-if="!collapsed"> <slot /> </td>
<td v-if="!collapsed"> col2 </td>
<td v-if="!collapsed"> col3 </td>
</tr>
'
});

const example = {};
const app = new Vue(example);
app.$mount("#app");

th, td {
border: 1px solid red;
padding: 1px;
}

.main-table {
border: 2px solid blue;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table class="main-table">
<thead>
<tr>
<th>Main Col 1</th>
<th>Main Col 2</th>
<th>Main Col 3</th>
</tr>
</thead>

<tbody>

<!-- This row has table inside table -->
<table-row :collapsed="1">
<p>title text</p>
<table>
<tr>
<th>embedded table header</th>
</tr>
<tr>
<td>embedded table text</td>
</tr>
</table>
</table-row>

<!-- This row is normal -->
<table-row :collapsed="0">
This row is not collapsed
</table-row>

<!-- This row is collapsed (hidden) -->
<table-row :collapsed="1">
This row is collapsed
</table-row>

</tbody>

</table>
</div>

спросил(а) 2019-02-04T17:47:00+03:00 2 года, 2 месяца назад
1
Решение
130

Я заставил это работать с функцией рендеринга vue, вы, вероятно, можете сделать это с шаблоном, но это будет дольше:

Vue.component("table-row", {
props: ["collapsed"],
render: function(h) {
if (this.collapsed == 1) {
return h('tr', [h('td', {attrs: {colspan: 3}}, 'collapsed')]);
}
return h('tr', this.$slots.default);
}
});

const app = new Vue({el: '#app'});

th, td {
border: 1px solid red;
padding: 1px;
}

.main-table {
border: 2px solid blue;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table class="main-table">
<thead>
<tr>
<th>Main Col 1</th>
<th>Main Col 2</th>
<th>Main Col 3</th>
</tr>
</thead>

<tbody>

<!-- This row has table inside table -->
<tr is="table-row" :collapsed="0">
<td>
<p>title text</p>
<table>
<tr>
<th>embedded table header</th>
</tr>
<tr>
<td>embedded table text</td>
</tr>
</table>
</td>
<td></td>
<td></td>
</tr>

<!-- This row is normal -->
<tr is="table-row" :collapsed="0">
<td>This row is not collapsed</td>
<td></td>
<td></td>
</tr>

<!-- This row is collapsed (hidden) -->
<tr is="table-row" :collapsed="1">
<td>This row is collapsed</td>
</tr>

</tbody>

</table>
</div>

Обратите внимание, что если вы используете слот в соответствии с моим примером, вам все равно придется включать узлы <td>.

ответил(а) 2019-02-04T19:16:00+03:00 2 года, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема