From f5f4ce90c1f178be30def8ef178e7a6ee356d96b Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Mon, 10 Feb 2020 08:13:13 +0100 Subject: [PATCH] DEV: adds afterRender decorator (#8864) --- .../discourse-common/utils/decorators.js.es6 | 14 ++++++ .../select-kit/select-kit-test-helper.js.es6 | 2 + test/javascripts/utils/decorators-test.js.es6 | 49 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 test/javascripts/utils/decorators-test.js.es6 diff --git a/app/assets/javascripts/discourse-common/utils/decorators.js.es6 b/app/assets/javascripts/discourse-common/utils/decorators.js.es6 index 053eefe341a..3339eb03fa5 100644 --- a/app/assets/javascripts/discourse-common/utils/decorators.js.es6 +++ b/app/assets/javascripts/discourse-common/utils/decorators.js.es6 @@ -1,6 +1,7 @@ import handleDescriptor from "ember-addons/utils/handle-descriptor"; import isDescriptor from "ember-addons/utils/is-descriptor"; import extractValue from "ember-addons/utils/extract-value"; +import { schedule, next } from "@ember/runloop"; export default function discourseComputedDecorator(...params) { // determine if user called as @discourseComputed('blah', 'blah') or @discourseComputed @@ -13,6 +14,19 @@ export default function discourseComputedDecorator(...params) { } } +export function afterRender(target, name, descriptor) { + const originalFunction = descriptor.value; + descriptor.value = function() { + next(() => { + schedule("afterRender", () => { + if (this.element && !this.isDestroying && !this.isDestroyed) { + return originalFunction.apply(this, arguments); + } + }); + }); + }; +} + export function readOnly(target, name, desc) { return { writable: false, diff --git a/test/javascripts/components/select-kit/select-kit-test-helper.js.es6 b/test/javascripts/components/select-kit/select-kit-test-helper.js.es6 index 70f81403015..828b656e5d5 100644 --- a/test/javascripts/components/select-kit/select-kit-test-helper.js.es6 +++ b/test/javascripts/components/select-kit/select-kit-test-helper.js.es6 @@ -3,10 +3,12 @@ import selectKit from "helpers/select-kit-helper"; export function testSelectKitModule(moduleName, options = {}) { moduleForComponent(`select-kit/${moduleName}`, { integration: true, + beforeEach() { this.set("subject", selectKit()); options.beforeEach && options.beforeEach.call(this); }, + afterEach() { options.afterEach && options.afterEach.call(this); } diff --git a/test/javascripts/utils/decorators-test.js.es6 b/test/javascripts/utils/decorators-test.js.es6 new file mode 100644 index 00000000000..507202a5b56 --- /dev/null +++ b/test/javascripts/utils/decorators-test.js.es6 @@ -0,0 +1,49 @@ +import { afterRender } from "discourse-common/utils/decorators"; +import Component from "@ember/component"; +import componentTest from "helpers/component-test"; + +const fooComponent = Component.extend({ + layoutName: "foo-component", + + classNames: ["foo-component"], + + baz: null, + + didInsertElement() { + this._super(...arguments); + + this.setBaz(1); + }, + + willDestroyElement() { + this._super(...arguments); + + this.setBaz(2); + }, + + @afterRender + setBaz(baz) { + this.set("baz", baz); + } +}); + +moduleForComponent("utils:decorators", { integration: true }); + +componentTest("afterRender", { + template: "{{foo-component baz=baz}}", + + beforeEach() { + this.registry.register("component:foo-component", fooComponent); + this.set("baz", 0); + }, + + test(assert) { + assert.ok(exists(document.querySelector(".foo-component"))); + assert.equal(this.baz, 1); + + this.clearRender(); + + assert.ok(!exists(document.querySelector(".foo-component"))); + assert.equal(this.baz, 1); + } +});