Make sure `didAppear` and therefore `resize` is called on change

Tables need to calculate their sizing depending on other things in the
DOM. When a table is in a tab panel, some of these things aren't visible
and therefore some values are zero during `didInsertElement`.

This commit ensures that the resize calc of the table is performed when
it's parent tab is clicked (and therefore when the table 'appears')
This commit is contained in:
John Cowen 2018-06-04 10:48:40 +01:00
parent 433ba16f17
commit cfc05fb413
7 changed files with 58 additions and 10 deletions

View File

@ -4,6 +4,7 @@ import identity from 'ember-collection/utils/identity';
import Grid from 'ember-collection/layouts/grid'; import Grid from 'ember-collection/layouts/grid';
import SlotsMixin from 'ember-block-slots'; import SlotsMixin from 'ember-block-slots';
import style from 'ember-computed-style'; import style from 'ember-computed-style';
import qsaFactory from 'consul-ui/utils/qsa-factory';
import { computed, get, set } from '@ember/object'; import { computed, get, set } from '@ember/object';
/** /**
@ -18,11 +19,8 @@ import { computed, get, set } from '@ember/object';
* in the future * in the future
*/ */
// basic DOM selecting utility, emeber doesn't like you using `$` // ember doesn't like you using `$` hence `$$`
// hence `$$` const $$ = qsaFactory();
const $$ = function(sel, context = document) {
return context.querySelectorAll(sel);
};
// basic pseudo CustomEvent interface // basic pseudo CustomEvent interface
// TODO: use actual custom events once I've reminded // TODO: use actual custom events once I've reminded
// myself re: support/polyfills // myself re: support/polyfills
@ -159,18 +157,18 @@ export default Component.extend(SlotsMixin, {
// TODO: Consider moving all DOM lookups here // TODO: Consider moving all DOM lookups here
// this seems to be the earliest place I can get them // this seems to be the earliest place I can get them
window.addEventListener('resize', this.handler); window.addEventListener('resize', this.handler);
this.handler(); this.didAppear();
}, },
willDestroyElement: function() { willDestroyElement: function() {
window.removeEventListener('resize', this.handler); window.removeEventListener('resize', this.handler);
}, },
didAppear: function() {
this.handler();
},
resize: function(e) { resize: function(e) {
const $tbody = [...$$('tbody', this.element)][0]; const $tbody = [...$$('tbody', this.element)][0];
const $appContent = [...$$('main > div')][0]; const $appContent = [...$$('main > div')][0];
if ($appContent) { if ($appContent) {
// TODO: This is zero if the tabular collection is in a tab
// need to make sure this also is calculated when
// things become visible
const rect = $tbody.getBoundingClientRect(); const rect = $tbody.getBoundingClientRect();
const $footer = [...$$('footer[role="contentinfo"]')][0]; const $footer = [...$$('footer[role="contentinfo"]')][0];
const space = rect.top + $footer.clientHeight; const space = rect.top + $footer.clientHeight;

View File

@ -1,7 +1,11 @@
import Controller from '@ember/controller'; import Controller from '@ember/controller';
import { get, set } from '@ember/object'; import { get, set } from '@ember/object';
import { getOwner } from '@ember/application';
import WithFiltering from 'consul-ui/mixins/with-filtering'; import WithFiltering from 'consul-ui/mixins/with-filtering';
import qsaFactory from 'consul-ui/utils/qsa-factory';
import getComponentFactory from 'consul-ui/utils/get-component-factory';
const $$ = qsaFactory();
export default Controller.extend(WithFiltering, { export default Controller.extend(WithFiltering, {
queryParams: { queryParams: {
s: { s: {
@ -26,6 +30,18 @@ export default Controller.extend(WithFiltering, {
); );
}, },
actions: { actions: {
change: function(e) {
set(this, 'selectedTab', e.target.value);
const getComponent = getComponentFactory(getOwner(this));
// Ensure tabular-collections sizing is recalculated
// now it is visible in the DOM
[...$$('.tab-section input[type="radio"]:checked + div table')].forEach(function(item) {
const component = getComponent(item);
if (component && typeof component.didAppear === 'function') {
getComponent(item).didAppear();
}
});
},
sortChecksByImportance: function(a, b) { sortChecksByImportance: function(a, b) {
const statusA = get(a, 'Status'); const statusA = get(a, 'Status');
const statusB = get(b, 'Status'); const statusB = get(b, 'Status');

View File

@ -45,7 +45,7 @@
) )
) as |panel| ) as |panel|
}} }}
{{#tab-section id=panel.id selected=(eq (if selectedTab selectedTab 'health-checks') panel.id) onchange=(action (mut selectedTab) value="target.value")}} {{#tab-section id=panel.id selected=(eq (if selectedTab selectedTab 'health-checks') panel.id) onchange=(action "change")}}
{{partial panel.partial}} {{partial panel.partial}}
{{/tab-section}} {{/tab-section}}
{{/each}} {{/each}}

View File

@ -0,0 +1,9 @@
export default function(owner, key = '-view-registry:main') {
const components = owner.lookup(key);
return function(el) {
const id = el.getAttribute('id');
if (id) {
return components[id];
}
};
}

View File

@ -0,0 +1,5 @@
export default function(doc = document) {
return function(sel, context = doc) {
return context.querySelectorAll(sel);
};
}

View File

@ -0,0 +1,10 @@
import getComponentFactory from 'consul-ui/utils/get-component-factory';
import { module, test } from 'qunit';
module('Unit | Utility | get component factory');
// Replace this with your real tests.
test('it works', function(assert) {
let result = getComponentFactory({ lookup: function() {} });
assert.ok(result);
});

View File

@ -0,0 +1,10 @@
import qsaFactory from 'consul-ui/utils/qsa-factory';
import { module, test } from 'qunit';
module('Unit | Utility | qsa factory');
// Replace this with your real tests.
test('it works', function(assert) {
let result = qsaFactory();
assert.ok(result);
});