From 17f28d4018f8534c5fdcc994566d697c50ac701f Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Wed, 4 Aug 2021 13:54:27 -0400 Subject: [PATCH] DEV: Add a widget API for injecting services When declaring your widget you can now add an option like: `services: ['cool']` And your widget instances will automatically get a `this.cool` property which will resolve to the service. This saves having to look it up yourself. --- .../discourse/app/widgets/header.js | 9 +++------ .../discourse/app/widgets/widget.js | 5 +++++ .../tests/integration/widgets/widget-test.js | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/discourse/app/widgets/header.js b/app/assets/javascripts/discourse/app/widgets/header.js index 0c292dea95e..bca43e1cec3 100644 --- a/app/assets/javascripts/discourse/app/widgets/header.js +++ b/app/assets/javascripts/discourse/app/widgets/header.js @@ -335,6 +335,7 @@ export function attachAdditionalPanel(name, toggle, transformAttrs) { export default createWidget("header", { tagName: "header.d-header.clearfix", buildKey: () => `header`, + services: ["router"], defaultState() { let states = { @@ -465,9 +466,7 @@ export default createWidget("header", { params = `?context=${context.type}&context_id=${context.id}&skip_context=${this.state.skipSearchContext}`; } - const currentPath = this.register - .lookup("service:router") - .get("_router.currentPath"); + const currentPath = this.router.get("_router.currentPath"); if (currentPath === "full-page-search") { scrollTop(); @@ -545,9 +544,7 @@ export default createWidget("header", { state.contextEnabled = false; - const currentPath = this.register - .lookup("service:router") - .get("_router.currentPath"); + const currentPath = this.router.get("_router.currentPath"); const blocklist = [/^discovery\.categories/]; const allowlist = [/^topic\./]; const check = function (regex) { diff --git a/app/assets/javascripts/discourse/app/widgets/widget.js b/app/assets/javascripts/discourse/app/widgets/widget.js index 27faa319f04..158f2138104 100644 --- a/app/assets/javascripts/discourse/app/widgets/widget.js +++ b/app/assets/javascripts/discourse/app/widgets/widget.js @@ -148,6 +148,11 @@ export default class Widget { this.appEvents = register.lookup("service:app-events"); this.keyValueStore = register.lookup("key-value-store:main"); + // We can inject services into widgets by passing a `services` parameter on creation + (this.services || []).forEach((s) => { + this[s] = register.lookup(`service:${s}`); + }); + this.init(this.attrs); // Helps debug widgets diff --git a/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js b/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js index 6d184679175..d8f7198f5a9 100644 --- a/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js +++ b/app/assets/javascripts/discourse/tests/integration/widgets/widget-test.js @@ -37,6 +37,24 @@ discourseModule("Integration | Component | Widget | base", function (hooks) { }, }); + componentTest("widget services", { + template: hbs`{{mount-widget widget="service-test"}}`, + + beforeEach() { + createWidget("service-test", { + tagName: "div.base-url-test", + services: ["router"], + html() { + return this.router.rootURL; + }, + }); + }, + + test(assert) { + assert.equal(queryAll(".base-url-test").text(), "/"); + }, + }); + componentTest("hbs template - no tagName", { template: hbs`{{mount-widget widget="hbs-test" args=args}}`,