Skip to content

Commit

Permalink
Dynamic tags
Browse files Browse the repository at this point in the history
  • Loading branch information
Akryum committed Dec 21, 2016
1 parent 52458c8 commit c46dfec
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 24 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,33 @@ There are additional props you can use:

- `typeField` to customize which field is used on the items to get their type and use the corresponding definition in the `renderers` map. The default is `'type'`.
- `keyField` to customize which field is used on the items to set their `key` special attribute (see [the documation](https://vuejs.org/v2/api/#key)). The default is `'id'`.
- `mainTag` to change the DOM tag of the component root element. The default is `'div'`.
- `containerTag` to change the DOM tag of the element simulating the height. The default is `'div'`.
- `contentTag` to change the DOM tag of the element containing the items. The default is `'div'`. For example, you can change this to `'table'`.

The component template is structured like this:

```html
<main>
<container>
<content>
<!-- Your items here -->
</content>
</container>
</main>
```

If you set `contentTag` to `'table'`, the actual result in the DOM will bu the following:

```html
<div>
<div>
<table>
<!-- Your items here -->
</table>
</div>
</div>
```

The `renderers` map is an object containing a component definition for each possible value of the item type. **The component definition must have an `item` prop, that will get the item object to render in the scroller.**

Expand Down
5 changes: 5 additions & 0 deletions dist/vue-virtual-scroller.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
}
.item-container[data-v-5594e8c4] {
box-sizing: border-box;
width: 100%;
overflow: hidden;
}
.items[data-v-5594e8c4] {
width: 100%;
}

.resize-observer[data-v-c7b3205a] {
Expand Down
2 changes: 1 addition & 1 deletion dist/vue-virtual-scroller.js

Large diffs are not rendered by default.

25 changes: 19 additions & 6 deletions docs-src/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
Virtual scroller update: {{ updateTime }} ms
</span>
<span>
<button @click="showScroller = !showScroller">Toggle scroller</button>
<button @mousedown="showScroller = !showScroller">Toggle scroller</button>
</span>
</div>
<div class="content" v-if="showScroller">
<virtual-scroller class="scroller" :items="items" :renderers="renderers" item-height="42" type-field="type" key-field="index"></virtual-scroller>
<div class="wrapper">
<virtual-scroller class="scroller" :items="items" :renderers="renderers" item-height="42" type-field="type" key-field="index" main-tag="section" content-tag="table"></virtual-scroller>
</div>
</div>
</div>
</template>
Expand Down Expand Up @@ -130,22 +132,26 @@ body {
position: relative;
}
.scroller {
overflow: auto;
.wrapper {
overflow: hidden;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.scroller {
width: 100%;
height: 100%;
}
.item-container {
box-sizing: border-box;
}
.item {
height: 42px;
padding: 12px;
box-sizing: border-box;
cursor: pointer;
user-select: none;
Expand All @@ -165,9 +171,16 @@ body {
}
.index {
display: inline-block;
color: rgba(0, 0, 0, 0.2);
width: 55px;
text-align: right;
}
table {
border-collapse: collapse;
}
td {
padding: 12px;
}
</style>
9 changes: 8 additions & 1 deletion docs-src/src/Item.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<template>
<div class="person" @click="edit"><span class="index">{{item.index}}</span> {{item.value.name}}</div>
<tr class="person" @click="edit">
<td class="index">
{{item.index}}
</td>
<td>
{{item.value.name}}
</td>
</tr>
</template>

<script>
Expand Down
9 changes: 8 additions & 1 deletion docs-src/src/Letter.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<template>
<div class="letter"><span class="index">{{item.index}}</span> {{item.value}}</div>
<tr class="letter">
<td class="index">
{{item.index}}
</td>
<td>
{{item.value}}
</td>
</tr>
</template>

<script>
Expand Down
10 changes: 5 additions & 5 deletions docs/build.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/build.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vue-virtual-scroller",
"description": "Smooth scrolling for any amount of data",
"version": "0.1.0",
"version": "0.2.0",
"author": {
"name": "Guillaume Chau",
"email": "guillaume.b.chau@gmail.com"
Expand Down
36 changes: 28 additions & 8 deletions src/components/VirtualScroller.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<template>
<div class="virtual-scroller" @scroll="updateVisibleItems">
<div class="item-container" :style="itemContainerStyle">
<div class="items">
<component :is="mainTag" class="virtual-scroller" @scroll="updateVisibleItems">
<component :is="containerTag" class="item-container" :style="itemContainerStyle">
<component :is="contentTag" class="items" :style="itemsStyle">
<component class="item" v-for="item in visibleItems" :key="item[keyField]" :is="renderers[item[typeField]]" :item="item"></component>
</div>
</div>

</component>
</component>
<resize-observer @notify="updateVisibleItems" />
</div>
</component>
</template>

<script>
Expand Down Expand Up @@ -40,11 +39,24 @@ export default {
type: String,
default: 'id',
},
mainTag: {
type: String,
default: 'div',
},
containerTag: {
type: String,
default: 'div',
},
contentTag: {
type: String,
default: 'div',
},
},
data: () => ({
visibleItems: [],
itemContainerStyle: null,
itemsStyle: null,
}),
watch: {
Expand Down Expand Up @@ -74,7 +86,9 @@ export default {
this.visibleItems = this.items.slice(startIndex, endIndex)
this.itemContainerStyle = {
height: l * this.itemHeight + 'px',
paddingTop: startIndex * this.itemHeight + 'px',
}
this.itemsStyle = {
marginTop: startIndex * this.itemHeight + 'px',
}
this.$forceUpdate()
},
Expand All @@ -97,5 +111,11 @@ export default {
.item-container {
box-sizing: border-box;
width: 100%;
overflow: hidden;
}
.items {
width: 100%;
}
</style>

0 comments on commit c46dfec

Please # to comment.