Modal Views - can we agree on a best practice?

I use method #1 in my application, but standardize it somewhat with a view mixin. If you use a template layout you can put the standard modal elements there and use the template to fill it with particular content.

// View mixin to create and control modal view that will
// be opened when user clicks on view. Method createModalView
// should be implemented on the view class that uses the mixin.
App.ViewWithModalMixin = Ember.Mixin.create({
	modalView: null,

	click: function() {
		this.showModalView();
	},

	close: function() {
		this.closeModalView();
	},

	closeModalView: function() {
		if (this.modalView)
			this.modalView.close();
	},

	// open modal view of relationship to show all
	// details
	showModalView: function() {
		this.closeModalView();
		this.modalView = this.createModalView();
        if (this.modalView)
	       this.modalView.append();		
	}
});

App.AssetsView = Ember.View.extend(App.ViewWithModalMixin, {
	templateName : 'assets/assets',
	createModalView: function() {
		return App.AssetModalView.create({
			controller: this.controller,
			baseView: this
		});
	}
});

App.AssetModalView = Ember.View.extend({
	layoutName : 'layouts/modal',
	templateName : 'assets/edit',
	showHeader: true,

	close: function() {
		this.destroy();
	}
});

Hi,

I am experimenting with a modal view with a mini embedded state machine inside.

See example here

http://jsbin.com/igubev/1/edit

What I can’t quite get my head around still is whether this logic should be in a Route class or a Controller class. The specific concerns between view, route and controller are still a little murky to me.

Also, could someone explain why I can’t see the return value of currentStateName in the modal template?

currentStateName: function() {
    return this.modalManager.get('currentState.name');
},

I presumed that the “generated” application controller just inherited properties from the route.

Do I have to wrap all this in a component or control instead? Still trying to figure out how to make this sufficiently modular. Or else just clutter up the application controller (which seems messy).

Just out of interest I’ve just done it this way. Seems to work nicely so far…

<script id="application" type="text/x-handlebars">
	{{wizard-newProject controller=controller visible=showNewProjectWizard}}
	<div style="border-spacing:4px; ">
		{{outlet}}
	</div>
</script>
<script id='components/wizard-newProject' type="text/x-handlebars">
	{{view De3.NewProjectWizard controllerBinding="controller" visible=visible}}
</script>

Just in case anyone hasn’t seen it, there’s now a cookbook page on modals: http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/

Thanks for the update! I think that many folks would be interested how to make it go with Bootstrap modal. Is it possible?

I’ve updated my pre-1.0.0 post on how to do Modals with Bootstrap with an update linking to the cookbook version.

@rrh I haven’t looked at later versions of Bootstrap, but I would hope the combination of the cookbook recipe and the code in my now outdated post should be enough for you to figure out how to do it.

Feel free to ask me questions if you get stuck.

I’ve been looking out ways to handle wizard flow kind of modals instead of user event triggering the modal. And I also like to have the route based modal. Is there any resource available to handle wizard kind of flow for CRUD operations?

2 Likes

There is now support for animated modals in liquid-fire.

4 Likes

I am completely new to Ember.js and evaluating it for my work. Also very glad to find this discussion about Modal view in Ember, since I have been struggling with it for couple of days now. I tried out the sample in the cookbook, it works out well for me. However, in the output window I can click outside of the Modal view to remove it from screen. How can I have this Modal view stays until users click its “Done” button? I need a Modal popup window for my work, and having trouble to create one with the Ember.js.

Hi,

I prefer option #1 too and I did similar to @buuda, with Mixins. The difference is that the Mixin is intended to be used on Controllers. I think that by this way you could apply some logic on Modals based on the Controller that is rendering it, like, for example, disable the modal ‘Ok/Confirm’ button if some property of the controller is true/false. Another thing that is handy, is that the method of the Mixin, that shows the Modal, returns a Promise, so you can bind an action of a button to a method of Controller and inside the method shows the Modal and wait for the answer true/Ok or false/Cancel from the Promise, this makes the code more readable and clear.

Example:

index.js

import Ember from 'ember';
import ModalSupport from '../mixins/modal-support';

export default Ember.Controller.extend(ModalSupport, {

  actions: {
    tryModal: function() {
      var _this = this;
      _this.modalFor({template: 'some-template', 
                      title: 'Some Title'})
        .then(function(){
          console.log('action ok was clicked');
        })
        .catch(function() {
          console.log('action cancel was clicked');
        });
    }
  }
});

index.hbs

<button {{action 'tryModal'}}>Show Modal</button>

Here is a GIst with a complete example (the example is based on Bootstrap Modals, but can be easily changed to another framework): http://goo.gl/ftosdY

2 Likes