# Render a component within a Widget. (Using select-kit components within plugin code)

**URL:** https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462
**Category:** Development
**Created:** [April 3, 2018, 12:55pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462 "2018-04-03T12:55:25Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![duranmla](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/duranmla/32/109295_2.png) [@duranmla](https://meta.discourse.org/u/duranmla)
#### Post date: [April 3, 2018, 12:55pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/1 "2018-04-03T12:55:25Z")

</div>

If we successfully define a select-kit component within a plugin we are easily able to use it within a \*.hbs template file using its `pluginApiIdentifiers` however, in order to attach that component within a widget using JS code I am not able to make it work. For instance:

I have:

```plaintext
import DropdownSelectBoxComponent from 'select-kit/components/dropdown-select-box';

export default DropdownSelectBoxComponent.extend({
  pluginApiIdentifiers: ['header-profile-dropdown'],
  ...
  
  autoHighlight() { ... },

  computeContent() {
    ...
    return items;
  },

  mutateValue(id) { ... }
});

```

Then I can go to any template I want to overwrite and write like:

_(taking as an example the discovery template)_

```plaintext
...
<div id="list-area">
        {{header-profile-dropdown}}
...

```

And the snippet above will work flawlessly, **BUT how I will include that component into a widget like:**

```plaintext
    api.reopenWidget('user-dropdown', {
        html(attrs, state) {
          if (this.site.mobileView) {
            return h('div.profile-dropdown-container', [
              this.attach('header-notifications', attrs),
              --> I NEED ATTACH THE COMPONENT HERE <--
            ]);
          }

          ...
        }
      });

```

> NOTE: much of the code has been skipped to keep the post brief. Feel free to ask for the full code if needed.

PD: I have already tried to describe this issue at [How to attach a component to a widget with just markup?](https://meta.discourse.org/t/how-to-attach-a-component-to-a-widget-with-just-markup/82634) but looks like it was a too complicated explanation so I am trying to reduce the information here to make it clear and try to find an answer.

---

<div class="post-metadata">

### Author: ![duranmla](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/duranmla/32/109295_2.png) [@duranmla](https://meta.discourse.org/u/duranmla)
#### Post date: [April 4, 2018, 12:51am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/2 "2018-04-04T00:51:54Z")

</div>

I think it was a matter of ask myself the right question: **“How to render a component within a widget?”** that’s why I updated the topic title. I have found few results already such as: [How to render Component inside Widget? - #2 by eviltrout](https://meta.discourse.org/t/how-to-render-component-inside-widget/52872/2) I will take a look and post any useful finding if it is needed.

---

<div class="post-metadata">

### Author: ![duranmla](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/duranmla/32/109295_2.png) [@duranmla](https://meta.discourse.org/u/duranmla)
#### Post date: [April 4, 2018, 12:59am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/3 "2018-04-04T00:59:53Z")

</div>

Sadly enough looks like it is not possible, simply put we need to find a way to create a widget instead to render what we need to and render a widget within a widget, cause using the connector there are a lot of limitations. Check also: [Rendering Component in decorativeWidget API](https://meta.discourse.org/t/rendering-component-in-decorativewidget-api/58537)

---

<div class="post-metadata">

### Author: ![Chong\_An\_Chen](https://avatars.discourse-cdn.com/v4/letter/c/59ef9b/32.png) [@Chong\_An\_Chen](https://meta.discourse.org/u/Chong_An_Chen)
#### Post date: [April 4, 2019, 7:25am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/4 "2019-04-04T07:25:00Z")

</div>

same issue here.  
this is really terrible frontend code that uses widgets and ember components in the same page, it’s really hard to revamp and maintain.  
can’t understand what’s the logic

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [April 4, 2019, 7:42am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/5 "2019-04-04T07:42:20Z")

</div>

An example of this is available in Discourse itself:

[https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6#L362](https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6#L362)

I wasn’t there when widgets were created, but as far as I can tell, it was created for performance reasons at a time where frontend and especially mobile frontend had huge performance issues. And for dev simplicity it was added the possibility to inject components into widgets.

You got to understand that Discourse carries some history and we can’t start from scratch every year.

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [April 5, 2019, 4:00pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/6 "2019-04-05T16:00:04Z")

</div>

This topic was automatically closed after 32 hours. New replies are no longer allowed.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 26, 2022, 1:22pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/7 "2022-08-26T13:22:51Z")

</div>

For the record - we have a new system for rendering Ember components within widgets. Details can be found in the commit message here:

[https://github.com/discourse/discourse/commit/6c5efb61c992fb9850f900b49f5df6ca57bfff9a](https://github.com/discourse/discourse/commit/6c5efb61c992fb9850f900b49f5df6ca57bfff9a)

Search for `RenderGlimmer` in the core codebase to find example uses.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 26, 2022, 1:23pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/8 "2022-08-26T13:23:11Z")

</div>



---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 26, 2022, 1:50pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/9 "2022-08-26T13:50:08Z")

</div>

This is great @David! … but why might I be struggling to import:

```plaintext
import { hbs } from "ember-cli-htmlbars";

```

```plaintext
Error: Could not find module `ember-cli-htmlbars`

```

when trying to use this in a Theme Component?

(i’m on latest `tests-passed`)

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 26, 2022, 2:17pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/10 "2022-08-26T14:17:50Z")

</div>

Ah… it’s very possible that inline-compilation doesn’t (yet) work in theme components. It should work in plugins (as of [this week](https://github.com/discourse/discourse/commit/b175513765a216e4ec07635e3ecbfc7def7c0560)). I’ll see what I can do to add theme component support :eyes:

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 26, 2022, 7:42pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/12 "2022-08-26T19:42:43Z")

</div>

This should get things working:

[https://github.com/discourse/discourse/pull/18112](https://github.com/discourse/discourse/pull/18112)

Will try and get it merged next week

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 26, 2022, 7:48pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/13 "2022-08-26T19:48:59Z")

</div>

Excellent progress. I have a use for this so looking forward to it :+1:t2:

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 29, 2022, 7:52pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/14 "2022-08-29T19:52:38Z")

</div>

That’s merged - let us know how you get on with it @merefield

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 29, 2022, 8:54pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/15 "2022-08-29T20:54:57Z")

</div>

Bingo! Component is now appearing in my TC-based widget, even data is populated correctly, awesome beans! :rocket:

Thanks for the amazing turnaround straddling the UK Bank Holiday!

I know that widgets handle click events, but what if my Component has an event which fires an action, where can I handle that action within a Widget?

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 29, 2022, 9:56pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/16 "2022-08-29T21:56:44Z")

</div>

Oops David, just seen an example, I’m studying it!

> <https://github.com/discourse/discourse/blob/3e010bc88c84eff1cc32d69b1b6fe5fc16305d8d/app/assets/javascripts/discourse/tests/integration/components/widgets/render-glimmer-test.js#L28>

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 29, 2022, 9:59pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/17 "2022-08-29T21:59:09Z")

</div>

Yup, that’s probably the best reference. I don’t think we’ve passed actions ‘for real’ yet in core, so shout if you run into any issues.

Looking at that test again, I suspect the `actionForComponentToTrigger()` function will need an `@bind` above it to make sure `this` works correctly within it.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 30, 2022, 3:29pm UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/18 "2022-08-30T15:29:14Z")

</div>

OK this works to an extent:

```plaintext
    contents.push(
      new RenderGlimmer(
        this,
        "div.tag-chooser-component",
        hbs`<TagChooser @id="list-with-tags" @tags={{@data.chosen}} @onChange={{action @data.onChangeUpdateTagSet}}/>
        <button onClick={{@data.actionForClick}} label="blah"/>`,
        {
          chosen: this.chosen,
          onChangeUpdateTagSet: this.onChangeUpdateTagSet,
          actionForClick: this.actionForClick
        }
      ),
    );
    return contents;
  },

  @bind
  onChangeUpdateTagSet(chosen) {
    this.chosen.push(chosen.lastObject);
  },

  @bind
  actionForClick () {
    console.log(this.chosen)
  }
});

```

`onChangeUpdateTagSet` is invoked for a change, and `actionForClick` is invoked on button press.

However, I’m struggling with keeping the Tag Chooser populated.

As soon as I introduce my custom action for `onChange`, the control fails to keep the selected tags up to date in it’s UI (even though my custom variable contains the correct values).

And if I don’t include my custom action for `onChange`, the components UI works again, but I can’t populate my set. :thinking:

I tried to add `this.scheduleRerender()` to the `onChangeUpdateTagSet` function but this is showing as `undefined` - clearly not in its scope?

I added a click event to the widget and it does then refresh showing the correct data.

However, it looks like the binding is only going one way so I can’t use the Component to update the external data, only push new data into the Component.

Is there a way to make the binding two way?

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 31, 2022, 8:57am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/19 "2022-08-31T08:57:56Z")

</div>

I suspect you’ll need to use [widget ‘state’](https://meta.discourse.org/t/40347#state-and-actions-4) rather than accessing `this.chosen` - widget instances are short-lived and ‘stateless’. You’ll get a new instance on each re-render, which means that `this.chosen` will be reset.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 31, 2022, 9:11am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/20 "2022-08-31T09:11:17Z")

</div>

`this.state` is undefined within the change function, so that makes things a bit tricky?

(I can pass it in, but that overwrites the data coming from the component to tell me what’s been chosen

```plaintext
  onChangeUpdateTagSet: this.onChangeUpdateTagSet(this.state),

```

)

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 31, 2022, 9:24am UTC](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462/21 "2022-08-31T09:24:12Z")

</div>

Are you able to share more of the widget code? IIRC for state to work you need to define a `buildKey` and a `defaultState()` method.

I’ll see if I can add add an example of this kind of thing in the MountWidget tests :eyes:

[Next page](https://meta.discourse.org/t/render-a-component-within-a-widget-using-select-kit-components-within-plugin-code/84462.md?page=2)
