Migrating from Liquid Fire modals to Ember Elsewhere modals in Ember.js

Chris Masters
Aug 1, 2016 · 7 min read

Current Liquid Fire example

A modal route added to the router

this.modal(“modal-track-upload-error”, {
dialogClass: “error-modal”,
withParams: “trackUploadError”
});

A query parameter added to the relevant controller

export default Ember.Controller.extend({
queryParams: [
‘trackUploadError’,
],
trackUploadError: false
});

The modal handlebars template

<h2 id=”error-modal-title”>Track Upload Error</h2>
<p>Lorem ipsum...</p>
<div class=”close-modal”>
<button {{action (route-action ‘tryAgain’)}} class=”button-large” id=”error-modal-button”>OK, got it</button>
</div>

Including the modal in the application template

{{liquid-modal}}

Styling the generated HTML

<div id=”ember587" class=”ember-view liquid-modal”>
<div id=”ember1076" class=”ember-view liquid-child”>
<div id=”ember1085" tabindex=”0" class=”ember-view lm-container”>
<div role=”dialog” class=”lf-dialog error-modal”>
<div id=”ember1090" class=”ember-view”>
<h2 id=”error-modal-title”>Track Upload Error</h2>
<p>Lorem ipsum...</p>
<div class=”close-modal”>
<button class=”button-large” id=”error-modal-button” data-ember-action=”1102">OK, got it</button>
</div>
</div>
</div>
</div>
<span id=”ember1111" class=”ember-view lf-overlay”></span>
</div>
</div>
.lf-overlay {
background-color: black;
opacity: 0.75;
}

Animating the transition

this.transition(
this.inHelper(‘liquid-modal’),
this.toValue(true),
this.use(‘explode’, {
pick: ‘.lf-overlay’,
use: [‘cross-fade’, {duration: 500, maxOpacity: 0.75}]
}, {
pick: ‘.lm-container’,
use: [‘cross-fade’, {duration: 500, delay: 500}]
}),
this.reverse(‘explode’, {
pick: ‘.lf-overlay’,
use: [‘cross-fade’]
}, {
pick: ‘.lm-container’,
use: [‘cross-fade’]
})
);

Displaying the modal using Ember Elsewhere

Installing Ember Elsewhere

ember install ember-elsewhere

Making a replacement modal component

ember g component modal-target
{{#from-elsewhere name=”modal” as |modal|}}
{{#if modal}}
<div class=”modal-background”></div>
<div class=”modal-container”>
<div class=”modal-dialog” >
{{component modal}}
</div>
</div>
{{/if}}
{{/from-elsewhere}}
.modal-background {
background-color: black;
opacity: 0.75;
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
}
.modal-container {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
}

Triggering the modal with the query parameter

{{#if trackUploadError}}
{{to-elsewhere named=”modal” send=”modal-track-upload-error” }}
{{/if}}

Handling actions and closing the modal

Install the addon

ember install ember-ignore-children-helper

Adding it to the modal window

{{to-elsewhere named="modal" send=(hash body=(component "modal-track-upload-error") onOutsideClick=(action (mut trackUploadError) false)) }}
{{#from-elsewhere name=”modal” as |modal|}}
{{#if modal}}
<div class=”modal-background”></div>
<div class=”modal-container” onclick={{action (ignore-children modal.onOutsideClick) }}>
<div class=”modal-dialog” >
{{component modal.body}}
</div>
</div>
{{/if}}
{{/from-elsewhere}}

Adding additional actions

<button {{action (route-action ‘tryAgain’)}} class=”button-large” id=”error-modal-button”>OK, got it</button>
<button {{action onClose}} class=”button-large” id=”error-modal-button”>OK, got it</button>
{{to-elsewhere named=”modal” send=(hash body=(component “modal-track-upload-error” onClose=(action (mut trackUploadError) false)) onOutsideClick=(action (mut trackUploadError) false)) }}

Animating the modal

export default Ember.Component.extend({
modalAnimation
});
function modalAnimation() {
return this.lookup(‘explode’).call(this, {
pick: ‘.modal-background’,
use: [‘fade’, { maxOpacity: 0.75 }]
}, {
pick: ‘.modal-dialog’,
use: ‘to-down’
});
}
{{#from-elsewhere name=”modal” as |modal|}}
{{#liquid-bind modal containerless=true use=modalAnimation as |currentModal|}}
{{#if currentModal}}
<div class=”modal-background”></div>
<div class=”modal-container” onclick={{action (ignore-children currentModal.onOutsideClick) }}>
<div class=”modal-dialog” >
{{component currentModal.body}}
</div>
</div>
{{/if}}
{{/liquid-bind}}
{{/from-elsewhere}}

Summary

Chris Masters

Written by

C'est anglais mais c'est bon.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade