1

First off in plain Html+css and no JS this is pretty easy to do :

table {
    border-collapse: collapse; 
}
tr {
    border: solid black 1px;
}
td{
  border: solid black 1px;
}

.outer-container {
    height: 190px;
    width: 620px;
}
.inner-container {
    width: 100%;
    height: 100%;
}
.table-header {
    width: 100%;
    overflow:hidden;
}
.table-body {
    height: 100%;
    width: inherit;
    overflow-y: scroll;
}

.col1, .col2, .col3, .col4, .col5 {
    width:320px;
    min-width: 320px;
}
<body>
<div class="outer-container"> <!-- absolute positioned container -->
<div class="inner-container">
    <div class="table-header" id="headerdiv">
        <table id="headertable" width="100%" cellpadding="0" cellspacing="0">
            <thead>
                <tr>
                    <th class="header-cell col1">One</th>
                    <th class="header-cell col2">Two</th>
                    <th class="header-cell col3">Three</th>
                    <th class="header-cell col4">Four</th>
                    <th class="header-cell col5">Five</th>
                </tr>
            </thead>
        </table>
    </div>
    <div class="table-body" onscroll="document.getElementById('headerdiv').scrollLeft = this.scrollLeft;">
        <table id="bodytable" width="100%" cellpadding="0" cellspacing="0">
            <tbody>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
                <tr>
                    <td class="body-cell col1">body row1</td>
                    <td class="body-cell col2">body row2</td>
                    <td class="body-cell col3">body row2</td>
                    <td class="body-cell col4">body row2</td>
                    <td class="body-cell col5">body row2 en nog meer</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
</div>
</body>

source

The issue is I have different code in my Vue.js app and am opting for not using html table dom tags and going with bootstrap to construct my table instead. Mainly because it allows me to use vue's for loops and create my table from the items I get in server api response. I tried and failed with tables the dom layout of html tables means what I want to do here just isn't possible in dom html tables.

but that doesn't matter I have a working Boostrap table :

enter image description here

the issue is getting the x and y scroll to work like in the snippet above.

EDIT :

I made a first attempt using one component (snippet not runnable, just using this tag for readability):

.container{
  width: 600px;
  height: 200px;
  .container-content{

    .table-header {
      width: 1220px;
      overflow:hidden;
    }
    .table-body {
      .red{
        height: 5px;
        width: 1220px;
        background-color: red;
      }
      float:left;
      height: 150px;
      width: inherit;
      overflow-y: scroll;
      padding-right: 16px;
    }
  }
}
<template>
   <div id="database" class="content">
     <br/>
     <h3 class="left">Database :</h3>
     <hr/>
     <div class="container">
       <b-container fluid v-if="posts && posts.length" class="container-content">
         <b-row class="table-header" v-bind:ref="tableheader">
           <b-col><h5>Titre</h5></b-col>
           <b-col><h5>Version</h5></b-col>
           <b-col><h5>ID</h5></b-col>
           <b-col><h5>Mise à jour</h5></b-col>
           <b-col><h5>Présence</h5></b-col>
           <b-col><h5>Link</h5></b-col>
         </b-row>
         <hr/>
         <div class="table-body" v-bind:ref="tablebody" v-on:scroll="handleScroll()">
           <div class="red"></div>
         <b-row v-for="post of posts" key=uuid()>
           <b-col>
             <div>{{post.title.split(' ').slice(0, 1).join(' ')}}</div>
           </b-col>
           <b-col>
             <div>{{post.title.split(' ').slice(2).join(' ')}}</div>
           </b-col>
           <b-col>
             <div>{{post.title.split(' ').slice(1, 2).join(' ')}}</div>
           </b-col>
           <b-col>
             <div>{{post.updated}}</div>
           </b-col>
           <b-col>
             <div>{{post.display}}</div>
           </b-col>
           <b-col>
             <div>{{post.code}}</div>
           </b-col>
         </b-row>
         </div>
       </b-container>
     </div>
   </div>
</template>

<script>
  import axios from 'axios'
  export default {
    name: 'database',
    data () {
      return {
        posts: [],
        errors: []
      }
    },
    methods: {
      handleScroll () {
        console.log('scrolling')
        this.$$['tableheader'].scrollLeft = this.$$['tablebody'].scrollLeft
      }
    },
    created () {
      var token = 'JWT'
      axios.get(`http://localhost:3000/api/allergyintolerance/`, {headers: { 'Authorization': token }})
        .then(response => {
          this.posts = response.data.entry
        })
        .catch(e => {
          this.errors.push(e)
        })
    }
  }
</script>

I do get the console log but there's an error :

enter image description here

So I wondered if there can only be refs or el on the first div under template? ergo per-component?

So I tried with several components (Same, just used snippets for readability) :

(Database.vue):

<template>
   <div id="database" class="content">
     <br/>
     <h3 class="left">Database :</h3>
     <hr/>
     <div class="container">
       <b-container class="container-content">
         <TableHeader/>
         <hr/>
         <TableBody/>
       </b-container>
     </div>
   </div>
</template>

<script>
  export default {
    name: 'database',

    methods: {
      handleScroll () {
        console.log('scrolling')
        document.ref['table-header'].scrollLeft = document.ref['table-body'].scrollLeft
      }
    }
  }
</script>

(TableHeader.vue) :

<template>
  <b-row id="table-header" class="table-header" v-bind:ref=tableheader>
    <b-col><h5>Titre</h5></b-col>
    <b-col><h5>Version</h5></b-col>
    <b-col><h5>ID</h5></b-col>
    <b-col><h5>Mise à jour</h5></b-col>
    <b-col><h5>Présence</h5></b-col>
    <b-col><h5>Link</h5></b-col>
  </b-row>
</template>

<script>
    export default {
      name: 'table-header'
    }
</script>
   

(TableBody.vue) :

<template>
  <div id="table-body" v-if="posts && posts.length" class="table-body" v-bind:ref=tablebody v-on:scroll="callParent()">
    <div class="red"></div>
    <b-row v-for="post of posts" key=uuid()>
      <b-col>
        <div>{{post.title.split(' ').slice(0, 1).join(' ')}}</div>
      </b-col>
      <b-col>
        <div>{{post.title.split(' ').slice(2).join(' ')}}</div>
      </b-col>
      <b-col>
        <div>{{post.title.split(' ').slice(1, 2).join(' ')}}</div>
      </b-col>
      <b-col>
        <div>{{post.updated}}</div>
      </b-col>
      <b-col>
        <div>{{post.display}}</div>
      </b-col>
      <b-col>
        <div>{{post.code}}</div>
      </b-col>
    </b-row>
  </div>
</template>

<script>
  import axios from 'axios'

  export default {
    name: 'table-body',
    data () {
      return {
        posts: [],
        errors: []
      }
    },
    methods: {
      callParent () {
        this.$parent.$options.methods.handleScroll()
      }
    },
    created () {
      var token = 'JWT'
      axios.get(`http://localhost:3000/api/allergyintolerance/`, {headers: { 'Authorization': token }})
        .then(response => {
          this.posts = response.data.entry
        })
        .catch(e => {
          this.errors.push(e)
        })
    }
  }
</script>

same exact result both visually and the error in chrome console as in the above screen captures.

I also tried with only id declaration and this.$$['table-header'].scrollLeft = this.$$['table-body'].scrollLeft but the error persists.

I see another issue that I'm going to run into eventually : I haven't managed to make the title clip with size of the container.

UPDATE :

I got rid of the error with : document.getElementById('table-header').scrollLeft = document.getElementById('table-body').scrollLeft but it remains that nothing happens.

should I just give up trying to do this in vuejs?

tatsu
  • 2,316
  • 7
  • 43
  • 87

1 Answers1

1

Ok so dropping bootstrap entirely was the solution here :

SASS / SCSS :

.container-content{
    width: 600px;
    height: 200px;
    .table-header {
      width: inherit;
      overflow:hidden;
      div{
        width: 250px;
      }
    }
    .table-body {
      .red{
        height: 5px;
        width: 1220px;
        background-color: red;
      }
      float:left;
      height: 150px;
      width: inherit;
      overflow-y: scroll;
      padding-right: 16px;
    }
  }

(Database.vue) :

<template>
   <div id="database" class="content">
     <br/>
     <h3 class="left">Database :</h3>
     <hr/>
     <div class="container">
       <div class="container-content">
         <TableHeader/>
         <hr/>
         <TableBody/>
       </div>
     </div>
   </div>
</template>

<script>
  export default {
    name: 'database',

    methods: {
      handleScroll () {
        document.getElementById('tableheader').scrollLeft = document.getElementById('tablebody').scrollLeft
      }
    }
  }
</script>

(TableHeader.vue) :

<template>
  <div id="tableheader" class="table-header webkit">
    <div><h5>Titre</h5></div>
    <div><h5>Version</h5></div>
    <div><h5>ID</h5></div>
    <div><h5>Mise à jour</h5></div>
    <div><h5>Présence</h5></div>
    <div><h5>Link</h5></div>
  </div>
</template>

(TableBody.vue) :

<template>
  <div id="tablebody" v-if="posts && posts.length" class="table-body" v-on:scroll="callParent()">
    <div class="red"></div>
    <div v-for="post of posts" key=uuid() class="webkit">
      <div>
        <div>{{post.title.split(' ').slice(0, 1).join(' ')}}</div>
      </div>
      <div>
        <div>{{post.title.split(' ').slice(2).join(' ')}}</div>
      </div>
      <div>
        <div>{{post.title.split(' ').slice(1, 2).join(' ')}}</div>
      </div>
      <div>
        <div>{{post.updated}}</div>
      </div>
    </div>
  </div>
</template>

<script>
  import axios from 'axios'

  export default {
    name: 'table-body',
    data () {
      return {
        posts: [],
        errors: []
      }
    },
    methods: {
      callParent () {
        this.$parent.$options.methods.handleScroll()
      }
    },
    created () {
      var token = 'JWT'
      axios.get(`http://localhost:3000/api/allergyintolerance/`, {headers: { 'Authorization': token }})
        .then(response => {
          this.posts = response.data.entry
        })
        .catch(e => {
          this.errors.push(e)
        })
    }
  }
</script>
tatsu
  • 2,316
  • 7
  • 43
  • 87