Mounting widget in raw template?

Part of what I love about the new widget structure is being able to reuse code in multiple places. But I’ve run into an issue when attempting to do this for the voting plugin.

I use widgets heavily on the page for an individual topic. It makes the build process much smoother. But I want to take the base parent widget I’ve built for the topic page and place it on the topic list. That would allow the user to interact with the topic from the list itself. This is easily the most common request I get for this plugin.

However, since the topic list is built using raw handlebars templates, you can’t mount a widget there.

I can get this done by reopening the topic list component and rebuilding the entire UI but that seems a bit extreme for something seemingly simple. I’m hoping someone has an idea for how to reuse a widget on a topic list. Thoughts?

1 Like

Unfortunately there just is no way to do this right now. Widgets are fairly incompatible with raw handlebars.

You can put a widget outside of the raw handlebars fairly easily if you can get away with that.

2 Likes

Makes sense, Robin. It gets tricky using a combination of widget decoration and plugin outlets. Since there’s no intent to port the topic list away from the raw templates (and I don’t disagree with this decision), it makes it difficult to work with the existing plugin outlets within the topic-list-item.

In my thinking, it would make sense to add a plugin outlet at the beginning of the loop in the topic-list:

https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/templates/components/topic-list.hbs#L18

Since there are a number of outlets being deprecated in exchange for widgets, I don’t think it would be too much to ask for an add. I’d be happy to create the PR if this is an acceptable way of coming at this.

I know there are more than one request for functionality being added to a topic list item (liking, bookmarking, voting) and this would make that process a lot easier.

Scratch that. It doesn’t work to add a plugin outlet there. The tr tag is created within the component extension. You’d have to prepend the raw template by reopening the component and somehow injecting html, which I’m pretty sure can’t be done.

So for now, I have no solution to this. I may need to postpone this feature until the environment changes. I would create a PR to make it possible but right now I’m not even sure how to go about it.

Can you explain what you’re trying to do? It’s not clear to me why you’d want to change that tr tag or decorate around it?

The voting plugin makes heavy use of widgets to do pretty much everything. All of the actions to increment and decrement votes for a topic and the user as well as the UI displayed to make it all work are widgets. And I still think that’s the best way to build it as it’s extremely flexible and clear as to what’s going on.

Since the voting box that handles everything is a widget, my intent was to simply reuse that code on the topic list and make it possible to vote/unvote/super-vote from a list. This isn’t something I personally would want but I understand some of the arguments for it.

This is where I start to butt heads with the code. The template where this widget should be inserted is a raw template. I can’t mount a widget in a raw template.

So I considered adding a plugin-outlet outside the raw template in the topic-list. But that means the code I mount is wrapped in a div outside the table row for the list item since the the component that uses the raw template creates the table row.

I’m not interested in changing the tr but somehow need to include a widget somewhere inside it.

I hope this makes sense.

2 Likes

@eviltrout It follows from this that you can’t render a component (any component) in a raw template right?

I’m trying to render the share-popup component in a topic list item. I could just re-create the functionality, but I’d prefer not to.

@david Any ideas?

1 Like

I think you are correct there, based on all of the raw templates in core.

I’m not sure of the exact history/reasons/implementation for raw templates, but maybe someone else from the team can chime in. (I would also be interested to know if there is a solution, or even if we can switch them to regular templates now :man_shrugging:)

3 Likes

Not a team member, but through my conversations with Robin on this I had the understanding that those raw templates render significantly quicker overall. It has to do with the sheer number of times the template is reused.

3 Likes

Yes, any non-ember rendering paths were purely done for performance reasons. The code is almost always harder to follow or has major limitations (values not updating) but performs much better.

It was mainly done because of android performance.

5 Likes