How to display a widget in the hamburger menu?

Hi,

I’d like to display a widget in the hamburger menu. I lookes at How to display "Discord Widget" in a dropdown button to figure it out. but I’m not able to show the button in the hamburger menu.
Here’s my code:

const showModal = require("discourse/lib/show-modal").default;

api.createWidget("modal-button", {
  tagName: "a.test",

  html() {
    return "Open Modal";
  },

  click() {
    showModal("fareharbor");
  }
});

api.decorateWidget("hamburger-menu:generalLinks", function(helper) {
  return [helper.attach('modal-button')];
});

What am I doing wrong?

4 Likes

From what I can tell, I believe your only issue is helper.attach() doesn’t exist.

You should be using helper.widget.attach()

2 Likes

Thanks for your fast reply!
I tried your suggestion, but it didn’t work either :man_shrugging:

I tried to add a simple html element with this:

api.decorateWidget("hamburger-menu:generalLinks", function(helper) {
  return helper.h("div", "test text");
});

And it didn’t work :thinking:

1 Like

Are you doing this from inside withPluginApi() ?

2 Likes

Not that I know. Should I?

This code works, however, as it properly adds the element in the hamburger menu:

api.decorateWidget("hamburger-menu:generalLinks", function(helper) {
  return {href: "", rawLabel: "test"}
});

image

But I don’t know if I can call showModal("fareharbor"); without using a widget.

And Happy Birthday. :slight_smile:

edit:
Heres’ my full code:

const showModal = require("discourse/lib/show-modal").default;

api.createWidget("modal-button", {
  tagName: "a.test",

  html() {
    return "Open Modal";
  },

  click() {
    showModal("fareharbor");
  }
});

// doesn't work
api.decorateWidget("hamburger-menu:generalLinks", function(helper) {
  return [helper.widget.attach('modal-button')];
});

// works
api.decorateWidget("hamburger-menu:generalLinks", function(helper) {
  return {href: "", rawLabel: "test"}
});

The return [helper.widget.attach('modal-button')]; part creates an empty link:

<li><a class="widget-link" href="" title=""><span class="d-label"></span></a></li>
4 Likes

Where does this code live? Are you using the admin custom menu to add this?

Also, can you try adding console.log(showModal) inside of the html() { } area and see what is logged in your console?

1 Like

Yes, I do.

Yes, it shows some normal stuff I guess (when I trigger the modal):
(e,t){t=t||{};var n=(0,c.getOwner)(this),s=n.lookup("route:application"),a=s.controllerFor("modal");a.set("modalClass",t.modalClass||"".concat((0,u.dasherize)(e).toLowerCase(),"-modal"));var i=t.admi…

But unless I’m misunderstanding something, my issue isn’t the modal interaction (which works), but placing my widget in the hamburger menu.

I followed this modal creation tutorial and it works perfectly, the custom button shows the modal.
image
image
The modal works.
Adding the widget button in a template works and triggers the modal.
Adding a regular link in the hamburger menu works.
…But adding the widget button in the hamburger doesn’t work and creates an empty link instead. Are there some restrictions of some kind when using decorateWidget with “hamburger-menu”? :thinking:

2 Likes

I’ve passed this on to the appropriate channel and it will be looked at soon. There may be a something preventing this from working properly.

Thanks for bringing this up :smile:

1 Like

Happy birthday, Jordan!

1 Like

The API was designed with the idea that everything in generalLinks would be a link widget:

https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/widgets/hamburger-menu.js#L189

So the example above is returning another Widget instance, when in fact you need to return one or more javascript object literals like in your working example. Those objects are the arguments to the link widget to make the links appear correctly.

It looks like the reason you want to do this is to open a modal. That’s achievable using an action. Try this:

const showModal = require("discourse/lib/show-modal").default;

api.reopenWidget('hamburger-menu', {
  openThing(e) {
     showModal('thing-modal');
  }
});

api.decorateWidget("hamburger-menu:generalLinks", function(helper) {
  return { action: 'openThing', label: 'open.thing' };
});

In this case I attach a new action called openThing to the hamburger menu, then trigger that via my link.

4 Likes