Routable modals like Facebook/Twitter

Hi everyone,

I’ve been searching high and low for a solution to this problem and can only find solution that do half the job.

Say I have a photo model and I want to be able to open a viewer modal for them.

At my /photos route I have an infinite scrolling grid of photos, and clicking on one opens the viewer modal. The URL should then update to /photos/:id (or could be something like /p/:id if necessary). When the modal is closed, the user should go back to the infinite scrolling grid without having lost their place.

However, photos are linked from other pages as well. So for instance, you could be on a /test page that contains a photo, and open it in the modal. The URL would update to the photo’s unique URL, but closing the modal would take you back to /test.

I see this behaviour a lot on sites like Facebook, Twitter, Pinterest, Dribbble etc, but I can’t figure out how to implement it in the Ember Way. I could try overriding the router URL manually on modal open/close, but I’m not sure if that’s safe. Alternatively sub-routes don’t seem like they’d work here, because modals can be opened from many different routes but maintain the top-level /p/:id format.

If anyone has any ideas would love the help!

2 Likes

hi, what you need is a component that show photos in a modal form. then when close de component still live current route.

edit: sorry I forget to ask what ember version do you use ?

Check into Ember Modal Dialog: Ember Observer

It’s able to do what you are after, I’ve got it working for a client …

@acorncom Can you describe how you have what op is requesting with that addon? From what I can tell the addon wouldn’t help with desired routing behavior, which is you have a photos/:id route that can either be opened into the main application or into a modal, in both cases I think op still wants the url to represent photos/:id.

I’ve tried this with various addons as well as my own custom modals but there doesn’t seem to be a way, in any case the closest I could get was the desired routing behavior, but the content behind the modal always being torn down when the route changes (to match the modal).

Ember router just doesn’t support branched routing so I really don’t think it’s possible at the moment, best solution seems to be using a query param to represent the modal route.

Sorry, didn’t read that carefully enough. :-/

@benking from what I’ve seen, the router is going to want your routable component to have a sub-route for every place you want the modal to appear. Don’t think you’ll be able to have one consistent url for photos while having different items loaded behind the scenes in my client’s app we had to resort to mixing for controller and route to handle that appropriately.

If someone has a better solution, I’m interested :wink:

@benking I asked a similar question here: Modal dialogs (routes) accessible from anywhere in the app (preventing route deactivation)

We concluded the same thing: milions of subroutes or query params routing. Both solutions are not good because you “fight” against the framework.

I think that branched routing is something useful and would be great to have in the framework.

Are there any discussion or plans on this subject?

Hmm, that is frustrating. I wonder if a potential workaround would be manually manipulating the URL? So the modal isn’t actually connected to a route.

Hey @benking - I built exactly what you want (and actually called it a RoutableModal, as well!).

Here’s how I did it:

  • Make a RoutableModal service
  • Inject route into that service class
  • Define a transitionTo method on that service that uses the router to generate a URL: this.get('router').generate(path, data) and sets a url property on the service. Now you can do this.get('routableModal').transitionTo('foo', 1) and the service knows the URL that it should show.
  • Make a RoutableModal component that injects the routable modal and shows (wait for it) an iFrame modal of your app w/ that URL (assuming a URL is set)… Put this component in your application template.

The clear gotcha here is that it’s an iFrame of your app, which is silly. We use websockets, already, to keep windows in sync, so this solution actually works really well for us.

We’ve optimized it a bit to preload the iFrame so when you click a link, the second app loads really quickly.

It might be worth writing up an issue in the RFCs repo to prompt further discussion …

2 Likes

For anyone who’s looking to implement something like this, I’ve just released an addon that does this - ember-routable-modal. Just add a special outlet to your application template, the addon mixin to a route, and you have a routable modal!

It works by basically intercepting transitions to a route that has the mixin applied through the afterModel hook, rendering the route template to an outlet at the application level, and updating the URL. So you can navigate to a modal from anywhere in your route tree and not lose your place. If you hit a modal URL directly, the closest parent route will be rendered underneath. And it also works with loading substates. :thumbsup: