Good evening, everyone,
I have a vue-template which should generate a table. The table header, more precisely the number of individual column headers can be determined dynamically via the "slots".
Unfortunately there is always the error that there can only be one root element.
How can I - as easy as possible - make sure that my components are inserted into the header anyway.
table.vue
<template>
<table>
<thead>
<tr>
<slot></slot>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
</template>
And this ist how i would like to use it:
<lbtable>
<th>Column 1</th>
<th>Column 2</th>
</lbtable>
Here the error-message: Cannot use slot as component root element because it may contain multiple nodes.
Edit:
Here you can find the example:
https://codesandbox.io/s/small-waterfall-k6fit
Try this! You just need to wrap <th> with <template> tag.
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<lbtable>
<template>
<th>Column 1</th>
<th>Column 2</th>
</template>
</lbtable>
</div>
</body>
</html>
<script>
Vue.component('lbtable', {
'template': `
<div>
<table border="1">
<thead>
<tr>
<slot></slot>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
</div>`});
new Vue({
el: "#app"
});
</script>
Related
When trying to render a component, the template string is rendering not where the component is defined in the HTML. Instead, the rendered HTML is getting rendered outside of my <table>.
Easiest way to describe this is with the code snippet below. Column 2 is appearing outside the <table> altogether, even tho I have <my-th></my-th> directly after my <th>Column 1</th>.
Why is this happening?
Vue.component('my-th', {
props: [],
template: `<th>Column 2</th>`
});
new Vue({
el: "#app"
});
body { background: white; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th>Column 1</th>
<my-th></my-th><!-- Column 2 -->
</tr>
</thead>
<tbody>
<tr>
<td>data 1</td>
<td>data 2</td>
</tr>
</tbody>
</table>
</div>
You need to use Vue's special is attribute in this scenario.
The browser will parse the HTML before Vue gets anywhere near it and any elements inside a table that aren't where they're supposed to be will be moved out. The browser doesn't know what a my-th is so it moves it out to before the table.
This is specifically a problem with templates defined in HTML where it will be parsed by the browser first. For the various other ways to specify a template it isn't an issue as Vue can see the template in its original form.
See https://v2.vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats for details.
Vue.component('my-th', {
props: [],
template: `<th>Column 2</th>`
});
new Vue({
el: "#app"
});
body { background: white; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<tr>
<th>Column 1</th>
<th is="my-th"></th><!-- Column 2 -->
</tr>
</thead>
<tbody>
<tr>
<td>data 1</td>
<td>data 2</td>
</tr>
</tbody>
</table>
</div>
I'm trying to create a vue component to all my datagrids, I'm using DataTables library (https://datatables.net/), so, i've already create my vue component:
GridDatos.vue
<template>
<div class="container">
<h4>{{titulo}}</h4>
<table id="example" class="table table-striped table-bordered nowrap" style="width:100%">
<thead>
<tr>
<th v-for="col in colNames">{{col}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>sssss</td>
<td>sssss</td>
<td>sssss</td>
<td>sssss</td>
<td>sssss</td>
<td>sssss</td>
</tr>
</tbody>
<tfoot>
<tr>
<th v-for="col in colNames">{{col}}</th>
</tr>
</tfoot>
</table>
</div>
The instance:
Vue.component('grid-datos', require('./components/GridDatos.vue').default);
And the usage:
<div id="app">
<grid-datos
url="/api/listadoContactos"
titulo="Mis Datos"
:col-names="('Name','Position','Office','Age','Start date','Salary')">
</grid-datos>
</div>
But the problem here is the table header, it seems to use the last array element as you can see in the screenshot:
Titles
Definitely i'm not setting the array correctly when call the component.
Could anybody help me?
Thanks a lot. Regards.
In Pandas and Seaborn we can create beautiful graphical displays. However sometimes the best thing to show are numbers, for example in a data frame or pivot table.
Are there tools available to generate a similarly attractive display of numbers? (Yes, I suppose I can export to word or excel but that would have been true for beautiful graphs too...)
I'd say it depends on your definition of attractive, but one can make simple clean looking tables from pandas using the pandas.DataFrame.to_html() function. Combine this with custom CSS, or Bootstrap CSS as below, and the results are decent.
import pandas as pd
sample_df = pd.DataFrame({'Column A': [1,2,3,4,5], 'Column B': [5,4,3,2,1], 'Column C': [100,200,300,400,500]})
with open('test_table.html', 'w') as f:
f.write(sample_df.to_html())
Then simply edit the output html with some CSS, in this case Bootstrap.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row mt-5">
<div class="col">
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th>Column A</th>
<th>Column B</th>
<th>Column C</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>1</td>
<td>5</td>
<td>100</td>
</tr>
<tr>
<th>1</th>
<td>2</td>
<td>4</td>
<td>200</td>
</tr>
<tr>
<th>2</th>
<td>3</td>
<td>3</td>
<td>300</td>
</tr>
<tr>
<th>3</th>
<td>4</td>
<td>2</td>
<td>400</td>
</tr>
<tr>
<th>4</th>
<td>5</td>
<td>1</td>
<td>500</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
Resulting in something simple looking like this:
Which could be saved to PDF etc.
I am simply trying to render a list in my view and I keep seeing the error:
[Vue warn]: Property or method "client" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
Here's my view:
<div class="col-xs-6 col-xs-offset-3 text-center" id="vueapp">
<div class="table table-awaken" v-if="clients">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr v-for="client in clients">
<td>{{ client }}</td>
</tr>
</tbody>
</div>
</div>
and my vue instance:
var vote = new Vue({
el: "#vueapp",
data: {
clients: [
{ name: 'x' }
]
}
})
It is because you have thead and tbody that are not children of a table element. Browsers do interesting things when you break HTML rules like that.
See these docs which state that tbody and thead must be children of a table.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead
If you wrap those elements in a table element, it begins working. I am not sure if this is because of Vue or the browser.
Try this HTML instead:
<div class="col-xs-6 col-xs-offset-3 text-center" id="vueapp">
<div class="table table-awaken">
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr v-for="client in clients">
<td>{{ client }}</td>
</tr>
</tbody>
</table>
</div>
</div>
And here is a working jsfiddle: https://jsfiddle.net/kg638x4f/
I am trying to render a table. The data is dynamic and comes from an array. It works fine, except: the table content is rendered outside of the table on top of the page.
I would like it to render inside the table. Would anyone be able to help?
This what the code looks like:
Vue.js:
Vue.component('word', {
props: ['word-list'],
template: '#word-template'
});
new Vue({
el: '#root'
});
HTML:
<div id="root">
<word :word-list="{{json_encode($commonWords) }}"></word>
<template id="word-template">
<table class="table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr v-for="(value, key) in wordList" :wordList="wordList">
<td> #{{ key }} </td>
<td> #{{ value }} </td>
</tr>
</tbody>
</table>
</template>
</div>
Note: This is used with Laravel, thats why there is an # before double curly braces.
You can't define the template for your component inside the template for your Vue. You need to move it outside.
<div id="root">
<word :word-list="{{json_encode($commonWords) }}"></word>
</div>
<template id="word-template">
<table class="table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr v-for="(value, key) in wordList" :wordList="wordList">
<td> #{{ key }} </td>
<td> #{{ value }} </td>
</tr>
</tbody>
</table>
</template>
If you leave the template for the component inside the template for the root, the root will compile the template for the component as part of it's own template.