Render modal from theme client-side plugin API

The reason it doesn’t work is because the modal itself is dynamically loaded. So when your script fires, the element you’re targeting is not in the DOM, and once it is a part of the DOM (when you trigger it with showModal) your script will have already fired.

If you want to fire a script when the modal is loaded, you can use the modal:body-shown app event.

Here’s a commented example:

<script type="text/discourse-plugin" version="0.8">
// when the modal:body-shown event fires, let's try to do some work. we pass the 
// msg object to try and target a specific modal
api.onAppEvent("modal:body-shown", msg => {
  // let's get the title of the modal from the msg object
  let title = msg.title;
  // and compare the current modal's title to see if it has the same title as 
  // the one we want to target. This is the same string you use for the title 
  // attribute you define for the d-modal-body component in your custom modal 
  // template
  if (title != "custom_modal_title") {
    // not the modal you want to target
    return;
  } else {
    // this is the one we want, so do your work here
    $(".modal-body").html("Hey there!");
    $('.modal-header').prepend('<h1>Above modal title</h1>')
  }
});
</script>

just a quick note, when you prepend things to modal-header they will not display correctly right away. This happens because modal-header is set to display: flex.

So, you have to play around with its styles a little bit, and even though I don’t understand why you’d want to add an image there it should be possible to prepend an image to the modal header using the same method.