Create popup/modal by using a dynamic if statement?


#1

Hi!

I have a list, and each item of the list is the same template re-used with different variables. Each item of the list contains a button, and if clicked, I’d like to show a popup/modal that is specific to the data context of the clicked item.

To do so, I thought to simply do the following:

HTML:

<template name='list_item'>
	{{#if requestShow item.name}}
		{{> add_popup item=item}}
	{{/if}}
        ...
        <input type='button' class='diary-add' />
</template>
<template name='add-popup'>
...
</template>

And I used the following events & helpers:

Template.list_item.events({
	'click .diary-add'(event, instance) {
		Session.set('add-x-to-diary', this.item.name);
	}
});
Template.list_item.helpers({
	'requestShow': function(rn) {
		return Session.get('add-x-to-diary') == rn;
	}
});

I thought that this way, if I clicked the button, the session variable would update and the if statement would then evaluate to true, thus showing the specific modal. Once the if statement evaluates to false again, the modal gets hidden.

I know that this doesn’t seem like an elegant way of solving this, but how do you think should I go about it otherwise? (Setting aside the fact that it doesn’t even work anyway)

Thanks!


#2

Nevermind, what I did actually works, I just still had a display: none on my popup css.


#3

You can also render directly with Blaze, like so:

const view = Blaze.renderWithData(Template.add_popup, { item }, document.body);
//...later
Blaze.remove(view);

This has the added benefit of not having your modal rendered inside your DOM tree, inheriting any cascading styles for example. Mobile devices also behave nicer, when your modals or overlays aren’t inside the “main” DOM tree.

Also, I should comment that using Session is considered a bad practice.


#4

Oh, now that’s pretty interesting! Thanks for putting that out there.

Edit: Wait, if not Session, what should I use instead? If I use a normal variable it won’t automatically update, will it?


#5

Here’s the guide about client side stores. Sadly I couldn’t find any mention of not using Session in the docs, but basically go for it, if you only store a few bits of state, but if you think you might end up cramming a whole bunch of state inside that Session, it might be best to rethink.


#6

Yeah this pattern is fine.
We’re using a similar pattern with a modal block template. The modal is rendered within the DOM tree of it’s caller, and allows the passing of callbacks for confirmation or cancellation.
As a block template, you can also pass content into the modal from outside, which is then appropriately wrapped into the modal.

An example of a delete confirmation modal looks something like this:

{{#if showModal }}
  {{#modal onConfirm=deleteItem onCancel=closeModal header="Are you sure?" }}
    <p>
      Are you sure you want to delete this item?
    </p>
    <p>
       <small>All sub-items connected to this item will also be deleted</small>
    </p>
  {{/modal}}
{/if}

Then the parent template contains the logic for the modal, and passes through the content. The modal just wraps the content block into the appropriate elements and styles to render a modal, and passes clicks on the confirm or cancel button back up to the parent via it’s callback.