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

Fixing virtual scrollbar flip flopping. Closes #552. #665

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion addon/components/lt-body.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ export default Component.extend({
*/
useVirtualScrollbar: false,

/**
* @property virtualScrollbarSettled
* @type {Boolean}
* @default false
* @private
*/
virtualScrollbarSettled: false,

/**
* Set this property to scroll to a specific px offset.
*
Expand Down Expand Up @@ -354,7 +362,10 @@ export default Component.extend({

_setupVirtualScrollbar() {
let { fixedHeader, fixedFooter } = this.get('sharedOptions');
this.set('useVirtualScrollbar', fixedHeader || fixedFooter);
this.setProperties({
useVirtualScrollbar: fixedHeader || fixedFooter,
virtualScrollbarSettled: true
});
},

onRowsChange: observer('rows.[]', function() {
Expand Down
85 changes: 44 additions & 41 deletions addon/templates/components/lt-body.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,62 @@
{{#lt-scrollable
tagName=''
virtualScrollbar=useVirtualScrollbar
virtualScrollbarSettled=virtualScrollbarSettled
autoHide=autoHideScrollbar
scrollTo=targetScrollOffset
onScrollY=(action 'onScroll')
}}
<div id={{concat tableId '_inline_head'}} class="lt-inline lt-head"></div>

<table class={{tableClassNames}}>
<tbody class="lt-body">
{{#if enableScaffolding}}
<tr class="lt-scaffolding-row">
{{#each columns as |column|}}
<td style={{html-safe (if column.width (concat 'width: ' column.width))}} class="lt-scaffolding"></td>
{{/each}}
</tr>
{{/if}}
{{#if virtualScrollbarSettled}}
<table class={{tableClassNames}}>
<tbody class="lt-body">
{{#if enableScaffolding}}
<tr class="lt-scaffolding-row">
{{#each columns as |column|}}
<td style={{html-safe (if column.width (concat 'width: ' column.width))}} class="lt-scaffolding"></td>
{{/each}}
</tr>
{{/if}}

{{#if overwrite}}
{{yield columns rows}}
{{else}}
{{#each rows as |row|}}
{{lt.row row columns
data-row-id=row.rowId
table=table
tableActions=tableActions
extra=extra
enableScaffolding=enableScaffolding
canExpand=canExpand
canSelect=canSelect
click=(action 'onRowClick' row)
doubleClick=(action 'onRowDoubleClick' row)}}
{{#if overwrite}}
{{yield columns rows}}
{{else}}
{{#each rows as |row|}}
{{lt.row row columns
data-row-id=row.rowId
table=table
tableActions=tableActions
extra=extra
enableScaffolding=enableScaffolding
canExpand=canExpand
canSelect=canSelect
click=(action 'onRowClick' row)
doubleClick=(action 'onRowDoubleClick' row)}}

{{yield (hash
expanded-row=(component lt.spanned-row classes='lt-expanded-row' colspan=colspan yield=row visible=row.expanded)
loader=(component lt.spanned-row visible=false)
no-data=(component lt.spanned-row visible=false)
) rows}}
{{/each}}

{{yield (hash
expanded-row=(component lt.spanned-row classes='lt-expanded-row' colspan=colspan yield=row visible=row.expanded)
loader=(component lt.spanned-row visible=false)
no-data=(component lt.spanned-row visible=false)
loader=(component lt.spanned-row classes='lt-is-loading' colspan=colspan)
no-data=(component lt.spanned-row classes='lt-no-data' colspan=colspan)
expanded-row=(component lt.spanned-row visible=false)
) rows}}
{{/each}}
{{/if}}
</tbody>
</table>

{{yield (hash
loader=(component lt.spanned-row classes='lt-is-loading' colspan=colspan)
no-data=(component lt.spanned-row classes='lt-no-data' colspan=colspan)
expanded-row=(component lt.spanned-row visible=false)
) rows}}
{{#if onScrolledToBottom}}
{{lt.infinity
rows=rows
inViewport=(action "inViewport")
exitViewport=(action "exitViewport")
scrollableContent=(concat "#" tableId " .lt-scrollable")}}
{{/if}}
</tbody>
</table>

{{#if onScrolledToBottom}}
{{lt.infinity
rows=rows
inViewport=(action "inViewport")
exitViewport=(action "exitViewport")
scrollableContent=(concat "#" tableId " .lt-scrollable")}}
{{/if}}

<div id={{concat tableId '_inline_foot'}} class="lt-inline lt-foot"></div>
Expand Down
2 changes: 1 addition & 1 deletion addon/templates/components/lt-scrollable.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{#if virtualScrollbar}}
{{#if (and virtualScrollbarSettled virtualScrollbar)}}
{{#ember-scrollable
classNames='lt-scrollable'
autoHide=autoHide
Expand Down
81 changes: 81 additions & 0 deletions tests/integration/components/light-table-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,85 @@ module('Integration | Component | light table', function(hooks) {
await click(element);
}
});

test('table body renders once when header is rendered in place', async function(assert) {
assert.expect(1);

this.owner.register('component:custom-row', RowComponent.extend({
didInsertElement() {
this._super(...arguments);
assert.ok(true, 'row is rendered once');
}
}));

this.set('table', new Table(Columns, this.server.createList('user', 1)));

await render(hbs`
{{#light-table table height='500px' id='lightTable' as |t|}}
{{t.head}}
{{t.body rowComponent=(component "custom-row")}}
{{/light-table}}
`);
});

test('table body renders once when header is fixed', async function(assert) {
assert.expect(1);

this.owner.register('component:custom-row', RowComponent.extend({
didInsertElement() {
this._super(...arguments);
assert.ok(true, 'row is rendered once');
}
}));

this.set('table', new Table(Columns, this.server.createList('user', 1)));

await render(hbs`
{{#light-table table height='500px' id='lightTable' as |t|}}
{{t.head fixed=true}}
{{t.body rowComponent=(component "custom-row")}}
{{/light-table}}
`);
});

test('table body renders once when footer is rendered in place', async function(assert) {
assert.expect(1);

this.owner.register('component:custom-row', RowComponent.extend({
didInsertElement() {
this._super(...arguments);
assert.ok(true, 'row is rendered once');
}
}));

this.set('table', new Table(Columns, this.server.createList('user', 1)));

await render(hbs`
{{#light-table table height='500px' id='lightTable' as |t|}}
{{t.body rowComponent=(component "custom-row")}}
{{t.foot}}
{{/light-table}}
`);
});

test('table body renders once when footer is fixed', async function(assert) {
assert.expect(1);

this.owner.register('component:custom-row', RowComponent.extend({
didInsertElement() {
this._super(...arguments);
assert.ok(true, 'row is rendered once');
}
}));

this.set('table', new Table(Columns, this.server.createList('user', 1)));

await render(hbs`
{{#light-table table height='500px' id='lightTable' as |t|}}
{{t.body rowComponent=(component "custom-row")}}
{{t.foot fixed=true}}
{{/light-table}}
`);
});

});