Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

template is being rendered above the table #72

Open
tonykaralis opened this issue Apr 19, 2022 · 13 comments
Open

template is being rendered above the table #72

tonykaralis opened this issue Apr 19, 2022 · 13 comments
Labels
question Further information is requested

Comments

@tonykaralis
Copy link

Hi,

I have copied your code over and am trying to simply get the example working. As far as searching, sorting, paging etc everything works fine. The one thing that doesn't is the rendering of the datasetitems. I'm certain there is some config I am missing.

image

As you can see the rows appear above the table even though the html is as the example in the docs.

This is the code:

Vue.component('v-select', VueSelect.VueSelect);
Vue.component('Dataset', VueDataset.Dataset);
Vue.component('DatasetItem', VueDataset.DatasetItem);
Vue.component('DatasetInfo', VueDataset.DatasetInfo); 
Vue.component('DatasetPager', VueDataset.DatasetPager);
Vue.component('DatasetSearch', VueDataset.DatasetSearch);
Vue.component('DatasetShow', VueDataset.DatasetShow);

var vm = new Vue({
        el: '#normsApp',
        data: {
            users: [{
                "_id": "EA265B20-45F2-953C-C534-3E2A7862059C",
                "isActive": false,
                "onlineStatus": "Do not disturb",
                "balance": 93683,
                "birthdate": "1946-07-22",
                "favoriteColor": "orange",
                "firstName": "Harper",
                "lastName": "Nolan",
                "name": "Harper Nolan",
                "company": "Tortor At Risus LLC",
                "email": "amet@posuerevulputate.co.uk",
                "phone": "(0111) 194 7651",
                "address": "P.O. Box 298, 5571 Mauris Rd.",
                "favoriteAnimal": "owl"
            }] // left the rest out for the sake of the example.
            
            cols: [
                {
                    name: 'Name',
                    field: 'name',
                    sort: ''
                },
                {
                    name: 'Email',
                    field: 'email',
                    sort: ''
                }
            ]
        },
        computed: {
            sortBy() {
                return this.cols.reduce((acc, o) => {
                    if (o.sort) {
                        o.sort === 'asc' ? acc.push(o.field) : acc.push('-' + o.field)
                    }
                    return acc
                }, [])
            }
        },
        methods: {
            click(event, i) {
                let toset;
                const sortEl = this.cols[i];
                if (!event.shiftKey) {
                    this.cols.forEach((o) => {
                        if (o.field !== sortEl.field) {
                            o.sort = '';
                        }
                    })
                }
                if (!sortEl.sort) {
                    toset = 'asc';
                }
                if (sortEl.sort === 'desc') {
                    toset = event.shiftKey ? '' : 'asc';
                }
                if (sortEl.sort === 'asc') {
                    toset = 'desc';
                }
                sortEl.sort = toset;
            }
        },
        mounted() {
            
        }        
    });
                               <dataset v-slot="{ ds }"
                                     :ds-data="users"
                                     :ds-sortby="sortBy"
                                     :ds-search-in="['balance', 'name', 'company', 'email', 'phone', 'address', 'favoriteAnimal']">
                                <div class="row" :data-page-count="ds.dsPagecount">
                                    <div class="col-md-6 mb-2 mb-md-0">
                                        <dataset-show />
                                    </div>
                                    <div class="col-md-6">
                                        <dataset-search ds-search-placeholder="Search..." />
                                    </div>
                                </div>
                                <div class="row mt-3">
                                    <div class="col-md-12 table-responsive">
                                        <table class="table table-striped">
                                            <thead>
                                                <tr>
                                                    <th v-for="(th, index) in cols" :key="th.field" :class="['sort', th.sort]" v-on:click="click($event, index)">
                                                        {{ th.name }} <i class="gg-select float-right"></i>
                                                    </th>
                                                </tr>
                                            </thead>
                                            <dataset-item tag="tbody">
                                                <template #default="{ row, rowIndex }">
                                                    <tr>
                                                        <td>{{ row.name }}</td>
                                                        <td>{{ row.email }}</td>
                                                    </tr>
                                                </template>
                                            </dataset-item>
                                        </table>
                                    </div>
                                </div>

                                <div class="row">
                                    <div class="col-6">
                                        <dataset-info class="mb-2 mb-md-0" />
                                    </div>
                                    <div class="col-6">
                                        <dataset-pager />
                                    </div>
                                </div>
                            </dataset>
@kouts
Copy link
Owner

kouts commented Apr 19, 2022

Hey @tonykaralis, vue-dataset doesn't include any styling by default.
The examples rely on Bootstrap 4 CSS for styling, you can include it via CDN for your tests, but I would suggest using
you own custom CSS classes to style it.

@tonykaralis
Copy link
Author

Thanks @kouts that makes sense. I have been able to sort it with some jquery for the moment. Nice library by the way, solid work!

@mg1075
Copy link

mg1075 commented Mar 9, 2023

The challenge described in the original post is not about styling, or so it seems to me. Because I am encountering this same issue when using a table, I took a screenshot of the generated DOM. The <tbody> and its <tr> tags are being rendered in the DOM outside the <table> element that, at least in the code, encloses the <tbody>. The <table>, <thead>, and next the closing </table> tags are rendered after the <tbody> and table rows. So the issue seems like a DOM rendering problem rather than one CSS should try to fix. FWIW, this problem does not appear in the table example found on the documentation site, but I also don't know what version of the codebase that example is using. https://vue-dataset-demo.netlify.app/examples/datatable/ The version of the code I used on my local to generate the screenshot is from the "next" branch.

2023-03-09_10-39-48

@kouts
Copy link
Owner

kouts commented Mar 9, 2023

Hey @tonykaralis, there's an example on the next branch as well:
https://next--vue-dataset-demo.netlify.app/examples/datatable/

If you can post a Stackblitz or a Codesandbox reproduction of your issue maybe we can pinpoint the problem.

@tonykaralis
Copy link
Author

@kouts thanks for the link. I did manage to get this working last year and have closed the issue :)

@mg1075
Copy link

mg1075 commented Mar 9, 2023

@kouts Sure. Here is a jsbin demo that replicates the issue.
https://jsbin.com/sokoredefe/1/edit?html,output

@mg1075
Copy link

mg1075 commented Mar 10, 2023

@kouts One workaround for the DOM placement of <table> structure tags is to try to use <div> tags and css to mimic a table. Kind of a hack, though; and problematic because of tag added that cannot have class applied.
The tag props only handles pure html tags. It could be useful to be able to assign a css .class or #id to the tag.

@mg1075
Copy link

mg1075 commented Mar 15, 2023

@tonykaralis - It would be interesting to know how you managed to resolve the issue.

I have not found the reason why it is happening for me or whether it has anything to do with using Vue from a cdn script as I'm attempting to do (just trying to enhance an existing html page rather than make a full spa site).

My current workaround involves using a hidden counter field to find the first instance of a dataset-item record, use tag="table" on the dataset-item, add css classes on the dataset-item that the browser applies to the table tag when rendering, and add a v-if to the <thead> inside the <template> so there is only one instance of <thead>. Similar to this:

<span class="d-none">{{ templateRowCounter = 0 }}</span>
<dataset-item tag="table" class="table table-sm table-bordered">                       
    <template v-slot="{ row, rowIndex, index }">
        <thead v-if="templateRowCounter === 0">
            <tr>
                <th>col 1</th>
                <th>col 2</th>
                <th>col 3</th>
                <th>col 4</th>
                <th>col 5<span class="d-none">{{ templateRowCounter = templateRowCounter + 1 }}</span></th>
            </tr>
        </thead>
        <tr>
            <td>{{ row.field_1 }}</td>
            <td>{{ row.field_2 }}</td>
            <td>{{ row.field_3 }}</td>
            <td>{{ row.field_4 }}</td>
            <td>{{ row.field_5 }}</td>
        </tr>
    </template>
</dataset-item>

@kouts kouts reopened this Mar 15, 2023
@kouts
Copy link
Owner

kouts commented Mar 15, 2023

@tonykaralis check the docs here about why this issue happens.
You might be able to fix it using a custom dataset item component but I haven't tried it.
Let us know here if you found a solution for this.

@kouts kouts added the question Further information is requested label Mar 15, 2023
@tonykaralis
Copy link
Author

@mg1075 I am also using vue from a cdn, not running a spa app either. The library was dropping the data in a tbody above the table instead of inside it. So my solution was super simple, I find the body of data and put it where I want it inside the mount method.

The function that gets called in my mount method.

   function positionDataInTable() {
        //The dataset library seems to drop the data in a tbody above the table instad of inside it. 
        //This fixes it.
        var tableBody = $('#bodyWithData');
        $('#mainTable').append(tableBody);
    }

The html:

<div class="col-md-12 table-responsive table-striped">
                    <table class="table table-sm" id="mainTable" style="font-size:1rem;">
                        <thead>
                            <tr>
                                <th class="border-top-0">Product</th>
                                 <th v-for="(th, index) in cols" :key="th.field" :class="['sort', th.sort, 'border-top-0', 'font-weight-bold']" v-on:click="click($event, index)">
                                     {{ th.name }} <i class="gg-select float-right"></i>
                                  </th>
                            </tr>
                         </thead>
                         <!-- i have ided the body, this allows me to find and it put it where it belongs-->
                         <dataset-item tag="tbody" id="bodyWithData" class="mb-2">
                              <template v-slot="{ row, rowIndex }">
                                   <tr style="cursor:pointer;">
                                         <th class="table-cell-breakWord" v-on:click="getProductNormDetails(row.Id)">{{ row.Name }}</th>
                                               td v-for="(col, colIndex) in cols" class="table-cell-breakWord text-center"> {getFieldData(colIndex, rowIndex)}}</td>
                                   </tr>
                               </template>
                               <template #noDataFound>
                                   <div class="alert alert-warning text-center">
                                       No data found matching the selected search parameters!
                                   </div>
                                </template>
                          </dataset-item>
                      </table>
</div>

Hope this helps, I fixed this almost a hear ago, luckily I left a comment ;)

@mg1075
Copy link

mg1075 commented Mar 15, 2023

@tonykaralis - Nice; thanks for sharing. The kludge I was using was adding a <tbody> around every row, but your workaround provides a cleaner result for the rendered html.

@tony-gutierrez
Copy link

Why doesnt this happen in the official example? Also why would a tbody be hoisted out of a table as invalid??

@tony-gutierrez
Copy link

Easiest thing to do is make sure your dataset is being rendered in a component, not by vue root...lame.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants