Attempt to attach Glimmer fails with error

AI-generated summary

A developer, merefield, encountered a TypeError: this.parentMountWidgetComponent is undefined error while attempting to render a Glimmer Component as a widget in the Poll plugin. The issue arose because this._findAncestorWithProperty("_emberView") failed to find a parent widget with the required property, due to the widget’s ancestry being lost during transitions. merefield traced the problem to the widget hierarchy not being properly maintained and the rerenderWidget() method not being called. david identified that the issue was due to the poll widget being mounted inside post HTML rather than via <MountWidget>, and proposed a fix in a pull request (#26675). merefield confirmed the fix resolved the issue, though the solution is temporary as the team plans to phase out the current widget system.

I’m working on a PR to the Poll plugin.

I’m attempting to render a Glimmer Component as a widget tree leaf as I’ve done several times before, but getting this strange error I’ve not seen before:

TypeError: this.parentMountWidgetComponent is undefined

firing on this line:

It seems that this.widget?._findView() || this._emberView

is undefined.

(this.widget exists)

My very early stage code is here:

Is it legal to use RenderGlimmer in this context?

This relies on an ancestor having this property?

this._findAncestorWithProperty("_emberView")

which comes back undefined.

Or itself having an _emberView (which it doesn’t)

I’m guessing the ancestor should have had it set here:

OK a bit more info.

When the Poll is rendered (as a tree of widgets), this line is executed, but when you transitiion back to vote, it is not, thus for some reason there is no ancestor with an “_emberView” (Or it is not being found)

The source of this problem might be that the widget is never re-rendered:

rerenderWidget() {

Is not fired again despite adding a new tree of widgets … so this property is never set.

… thus the solution to this might be scheduling a re-render when the Vote button is hit …

  toggleResults() {
    **this.scheduleRerender();**
    this.state.showResults = !this.state.showResults;
  },

… no this doesn’t solve it.

More info:

  _findAncestorWithProperty(property) {
    let widget = this;
    while (widget) {
      const value = widget[property];
      if (value) {
        return widget;
      }
      widget = widget.parentWidget;
    }
  }

This is searching up the tree for the property.

On the initial view this appears at the post-stream level.

But somehow the widgets appear to be losing their ancestry …

OK so I’ve dug a little further:

This is the hierarchy the widget traversal occurs up:

discourse-poll-option-dropdown-245da0f65a66dbd539bcd27e501d759a [widget.js:250:14](webpack://discourse/widgets/widget.js)

discourse-poll-option-245da0f65a66dbd539bcd27e501d759a [widget.js:250:14](webpack://discourse/widgets/widget.js)

poll-container-poll-1247 [widget.js:250:14](webpack://discourse/widgets/widget.js)

poll-poll-1247

Now the very last, existing widget … has no parent widget.

parentWidget is undefined.

And the kicker is that it has no “_emberView” property, so the result is undefined

So the property is never found and at that point the traversal stops.

The poll plugin is a little unusual in that the widget is mounted inside a post’s cooked HTML, rather than directly inside an Ember template via the <MountWidget component. So we probably need to add some extra logic here… will take a look :eyes:

Thanks for reporting @merefield!

I think if we merge this, it should make your code work @merefield

https://github.com/discourse/discourse/pull/26675

It’s not particularly pretty, but I think it’s ok since this is a pretty rare situation, and we hope to totally rip out all this widget/RenderGlimmer stuff in the not-too-distant future :crossed_fingers:

Thanks David. Yes it makes sense that a compromise might suffice in the meantime :+1:

I’ll test it once/if it is merged (and I’ll have to update my fork! :sweat_smile:)

Really appreciate the fast turnaround on this one, David.

I can confirm this is now working for me.

I’ll post here if I find any further issues with this arrangement.

(Screenshot Caveat: Very early days for this project!)