Render modal from theme client-side plugin API

Creating a new modal involves 4 steps.

1. creating the template for the modal

You can create a new template like so:

<script type="text/x-handlebars" data-template-name="modal/custom-modal">
{{#d-modal-body title="custom_modal_title" class="custom-modal"}}
  Your content goes here!
{{/d-modal-body}}
</script>

A few quick notes about this:

  • The path you set in data-template-name must start with modal/ followed by your template name
  • {{d-modal-body}} is required
  • The title attribute on {{d-modal-body}} is the title that show at the top of the modal
  • it’s a good idea to add unique classes to your modal

2. Adding a title for the modal

If you notice above, the title for {{d-modal-body}} is set to “custom_modal_title” so we need to define what that is and you can do it like so

let currentLocale = I18n.currentLocale();
I18n.translations[currentLocale].js.custom_modal_title = "My custom modal";

3. creating a trigger for the modal

For this I’m going to be reusing the method I described in my previous post. Create a widget and show the modal when the widget is clicked but anything equivalent is fine as well. All you need is to get showModal() to fire somehow depending on what you have to work with.

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

api.createWidget("modal-button", {
 tagName: "button.btn.btn-primary",

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

 click() {
   showModal("customModal"); // name is the same you use for the new modal template in camelCase
 }
});

4. Add the widget to a template somewhere

Again, I’ll go back to my previous example and use

<script type="text/x-handlebars" data-template-name="/connectors/topic-above-post-stream/modal-button">
  {{mount-widget widget="modal-button"}}
</script> 

which would add the widget (button) right under the topic title on topic pages.

Now all you have to do is put all of this together and add it to the header section of your theme / theme component

<script type="text/x-handlebars" data-template-name="modal/custom-modal">
{{#d-modal-body title="custom_modal_title" class="custom-modal"}}
  <h1>Hello World!</h1>
{{/d-modal-body}}
</script>


<script type="text/discourse-plugin" version="0.8.18">
let currentLocale = I18n.currentLocale();
I18n.translations[currentLocale].js.custom_modal_title = "My custom modal";

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

api.createWidget("modal-button", {
  tagName: "button.btn.btn-primary",

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

  click() {
    showModal("customModal");
  }
});
</script>

<script type="text/x-handlebars" data-template-name="/connectors/topic-above-post-stream/modal-button">
{{mount-widget widget="modal-button"}}
</script> 

and you will have created a custom modal. :+1:

I’ve put together a small demo on theme-creator. Just visit any topic page and click on the “open modal” button below the title.

9 Likes