Position of modal (semantic ui popup)

HI all,

Just a simple question, How can I position the popup (a semantic ui modal)

I now include the modals somewhere in the top or bottom of my template. How can I make sure they are somewhere in the top center, and maybe have a scroll bar? (I already removed the bootstrap package, and searched a lot on google)

 <div class="ui modal APIAutomation">
        <div class="ui icon message">
            <img class="icon" src="images/API.png">
            <div class="content">
                <div class="header">
                    <h4> API automation: a quick introduction</h4>
                </div>
                <p>Please note there is no sound yet...</p>
                <p>This <a href="https://github.com/QHose/QRSMeteor">open source</a> (non-Qlik) <a href="https://www.meteor.com/">Meteor.js</a> based demo platform has been designed to demonstrate the power of the Qlik Sense API's for companies that are looking to integrate Qlik Sense in their multi-tenant SaaS platform. Please look at the video below for an introduction. In the demo you will see a screen divided into two parts.</p>
                <ul>
                    <li> The left side shows "the broker" in your SaaS platform; a piece of software that you already use today to mass maintain the SaaS applications for all of your customers. This broker executes its activities based on the list of your customers, their access rights and the relevant template apps (depending on what the customer has configured in your platform).
                    </li>
                    <li>The right side shows you the result of the activities of the broker; the apps and streams automatically created in Qlik Sense.</li>
                </ul>
                <p> This demo guides you on how you can automate each manual step in Qlik Sense. Sense works internally with the same API's as you can use, so you can record the REST call from each manual activity in the QMC and use this code to create/delete/reload/publish streams and apps in your software. We will not cover all the use cases, lets say we cover 80%, but the examples and code provided should give you enough convidence to build the remaining 20% yourself.</p>
            </div>
        </div>
        <div class="ui one column centered grid">
            <div class="column centered">
                <div class="ui embed" data-url="https://www.youtube.com/embed/wVVbP7a5-I8" data-placeholder="/images/API.png"></div>
                <!-- <iframe width="854" height="480" src="https://www.youtube.com/embed/wVVbP7a5-I8" frameborder="0" allowfullscreen></iframe> -->
            </div>
        </div>
        <div class="actions">
            <div class="ui positive right labeled icon button">
                I got it...
                <i class="checkmark icon"></i>
            </div>
        </div>
    </div>
</template>

thank you so much!

I have found this to be a slightly tricky one (when populating a modal with dynamic content) – to start, try running the following in your browser console when you have a modal up:

$('.ui.modal').modal('refresh');

More often than not, this will correctly position the modal and provide scrolling (if it is necessary).

If you find that this line of code is what you need to position the modal, then you will have to determine how best to use it. One pattern I’ve found that works pretty consistently:

//client.html
<template name="modalContent">
  <!-- this is the content that is actually *inside* the modal -->
  {{#each items}}
    <div>
      <p>{{name}}</p>
    </div>
  {{/each}}
  {{> modalRefresher}}
</template>

<template name="modalRefresher">
</template>

//client.js
Template.modalRefresher.onRendered(function() {
  $('.ui.modal').modal('refresh');
});

The modalRefresher won’t fire until the #each is looped through.

Coming up with a better approach is on the roadmap for the project where I’m using this pattern, so I’ll post back with an update if we are able to realize something better.

1 Like

Hey, thanks a lot! this is cool code. It not only solves the dynamic content issue (like I now had with autoform), but it also makes the size of the modal correct.

in stead of

How did your project go?

Strange… I commented out the include of the refresher {{> modalRefresher}} and put it back in, and now it doesn’t work anymore… So I am glad I already made the screenshots!

OK, you can solve this issue by putting the change event on the included template

<div class="ui modal insertCustomer">
            {{> insertCustomer}} {{> modalRefresher}}
        </div>

Template.insertCustomer.events({
    'change' () {
        console.log('something changed');
        $('.ui.modal.insertCustomer').modal('refresh');
    },
})

no… there is a bug in meteor. Now I checked it again by commenting it… and problem is back

ok, I noticed that the events are not triggered. Now I removed a missing link to my favicon.ico and it suddenly works again…:

ok, a workaround

'click .insertNewCustomer' () {
        $('.ui.modal.insertCustomer')
            .modal('show');
        Meteor.setTimeout(function(){refreshModal()}, 1);
        Meteor.setTimeout(function(){refreshModal()}, 2);
    }

Not so pretty, because the modal jumps up after a while, and is correct after this. I needed to fresh it 2 times. The first time only the position changed, the second time also the total height (fits content).

Another caveat – because the modal is generated outside of the scope of the template where it is called, blaze events don’t play well. Rather than trying to attach events to elements in the modal template, I attach the events to the template inside the modalContent div. Let me know if this makes sense/helps.

<template name="imagePickerModal">
  <div id="imagePickerModal" class="ui modal">
    <i class="close icon close-modal"></i>
    <div class="header" id="modalHeader">
      {{header}}
    </div>
    <div class="content" id="modalContent">
      {{> imagePicker}}
    </div>
  </div>
</template>

Hi,

Yes I think I already do that. I played around again today. And this is the most simple code I could make. The key thing is that you have to refresh the modal 2 times!

Template.users.events({
     'click .insertNewCustomer' () {
        $('#insertCustomer')
            .modal({ observeChanges: true })
            .modal('show');
            refreshModal();
    }

});


function refreshModal() {
    Meteor.setTimeout(function() { refreshModal() }, 1);
    return $('#insertCustomer').modal('refresh');
}

template

<template name='users'>
    {{> stepsRow}}
    <div class="ui two column stackable grid">
        <div id="insertCustomer" class="ui modal">
            {{> insertCustomer}} 
        </div>

If you refresh only once the modal is too long (white space)

with 2 refreshes you get a perfect modal

Why is this needed?

I think yogiben admin was also part of the trouble (which I think imports bootstrap by default), I removed it and I see different positioning now…

Guys, has anyone found a satisfactory solution to this yet?

My use case is that I have a number of templates with each launching its own modal - and because SUI detaches the modal (away from the template), I’ve set detachable to false and scoped the “show” event to the template instance like so:

templateInstance.$(".ui.modal").modal({detachable: false}).modal("show");

Now, the modals are positioned like they’re within the container the parent template is in - even if I make it a .fullscreen

I also removed yogiben:admin and twbs:bootstrap following @hoser23331’s suggestion. The only difference I’ve found is that you only need one .modal("refresh") instead of two. But even one refresh is too much! And… y’know… I still need an admin package…

Does anyone have any bright ideas?

(As an aside, I love and am grateful for Semantic UI - and it’s too late for me to change it for this project - but how viable is it really when everything requires an hour on stackoverflow and an undocumented hack to make it work? It’s one thing to be tweaking margins & padding to get things just right, but stuff like modals should work straight out of the box, right? Or am I being naive…?)

So the story continues. this is a cleaner approach. But yeah… I really need to call it twice!

Template.webIntegration.events({
    'click .webIntegrationMindMap' () {
        $('.ui.modal.webIntegrationMindMap')
            .modal('show')
            .modal('refresh')
            .modal('refresh');
    }
})

see @vigorwebsolutions answer, you can do a smart trick by putting the modal inside the template… and you can specify a context in semantic that puts it in a specific DIV