Best practice of queueing modal boxes?

I’m relying heavily on modal boxes to interact with the users. One difficulty I have is how can I queue modal boxes effectively in Meteor, so that eg I displaying the login box for a third party service before displaying the modal box the user was intended to use (but he hasn’t given the credentials yet, hence I need to popup the login modal first).

I’m using peppelg:bootstrap-3-modal package but obviously putting modal on top of modal doesn’t look nice. What I want is a modal popping up, users enters information, clicks submit (or cancel), if he clicks submit some action happens (checking credentials in my example) and if all is ok the login modal closes (it’s not the useraccount login, it’s a custom 3rd party one) and then shows another modal.

How can this be achieved and how have you guys solved such a situation?

Thanks in advance,

Andreas

This is an application logic state question instead of UI. Depending on the complexity of your application, if the conditions are becoming difficult to track or understand in your brain by glancing the code, I’d suggest to use FSM pattern for which you only need to check your FSM diagram and/or centralised definitions to understand / change the logic. Here’s a package I used to manage a casual game with 10+ states and many times more events triggering state changes: https://atmospherejs.com/natestrauser/statemachine.

You answered the question yourself… one needs a queue of some sort.

A null collection on the client can act as an unordered queue.

ModalQueue = new Mongo.Collection(null);

You can make it into an ordered queue by making sure each record has a timestamp and sorting along it.

ModalQueue.find({},{sort: {createdAt: -1}});

Some people go a step further, and implement an Action pattern:

ActionQueue = new Mongo.Collection(null);

ActionQueue.insert(new Action("authorize"));
ActionQueue.insert(new Action("login"));
ActionQueue.insert(new Action("news"));

ActionQueue.find({},{sort: {createdAt: -1}}).fetch()[0]

If using a collection is too much overhead, it’s also possible to implement a poor-person’s queue in the DOM using the CSS z-index property and :first-child pseudo element. Might require a bit of jQuery to push/pop elements, though.

1 Like

Thanks for the extensive tips on how to build a queue via a collection. I will surely consider this though I only have a rather simple flow of two modal boxes I need to manage.

The challenge for me is that I catch the template.event first which triggers me checking if the credentials were already given or not. If they were given I just push the modal. That flow path is simple and working.

The flow path that isn’t working is in the case the user hasn’t given the crucial credentials for the 3rd party login yet. So I have to show the modal for capturing that but catching the event that he clicks on the submit button for that first modal is somewhere else in my code (actually in a different template). In case his credentials are correct we can then open the second modal (that the user wanted to use in the first place).

What’s the best way to achieve this? Is it using a session variable that is covering the different stages of the flow? Then I could divert on successful submit event for the first modal from the usual flow if the session variable indicates that he actually wanted to go to another modal.

Hope you can understand what I mean. I need something to track and guide through the different actions possible in this flow.

I checked this statemachine package but it has basically no documentation and I’m not proficient enough with Meteor to go through the source code to find out if it is a valid solution and how to use it. I anyway have a rather sceptic view on packages without documentation, they tend to be neglected after a while and when you run into issues you’re usually left alone (that’s my experience so far).

The statemachine Meteor package is just a wrapper of a popular and mature JS library. Anyway, it should be an overkill for you simple use case.

Since you need cross Template state checking, though not recommended, I believe Session is simplist way you could have.

Having said that, If you are to stay with Blaze, I’d recommend to use ViewModel, the Share feature allows you to manage such cross template state elegantly, with tons of other goodies that could make your life much easier.

What is ViewModel? I’m here to stay with Blaze, yes, React would be an overkill IMO

ViewModel uses Blaze, http://viewmodel.meteor.com . You can then easily doing something like this

Template.credentials.viewmodel({
modalOpened:false,
username:null,
password:null,

checkCreds() {
 if(this.username() && this.password()) {

 this.modalOpened(true);

  } else { 

 this.modalOpened(false);
  }
 }
});

Template

<template name="credentials">
<input type="text" {{b "value:username"}} placeholder="Your username">
<input type="password" {{b "value:password"}} placeholder="Your password">
<button {{b "click:checkCreds"}}>Login</button>
{{#if modalOpened}}

<div class="modal">
  ......
</div>

{{/if}}
</template>

Just a note here: You can use every ViewModel property also as a template helper, so it’s very easy to use :slight_smile: