How to open a modal from any state using UI-Router

This post is a follow-up to a question that was asked on the AngularJS Poland Facebook group. One of the members wanted to open a modal window from anywhere in the app using UI-Router. At first this seemed simple enough. This is a common problem – so common that it has a section in the UI-Router FAQ.

Using a modal child state

The most simplified example goes like this:

In the above plunker we have two states defined – a parent state for the view (index) and a child state for the modal (index.terms). The child state doesn’t have a template nor controller as this isn’t an actually usable state. The magic happens because UI-Router executes the onEnter callback. This callback has the dependency injection system build in, and can open the modal dialog using the $modal service.

This works fine, unfortunately, this didn’t solve the initial problem – opening the modal window from anywhere in the app. In the above example, the modal state is a child of the index state, and opening it from any state other than index will cause UI-Router to switch to index. To solve this problem we need to take a different approach.

Using the $stateChangeStart event

This approach involves defining a placeholder state for the modal (terms in the above plunker) which is a top-level state. Next we need to listen to the $stateChangeStart event. UI-Router broadcasts this event from the $rootScope using Angulars event system every time a state is about to change. Among the arguments passed to the event listeners this event passes the toState object. We can use this to check which state is to be displayed, display the modal dialog using the $modal service, and cancel the state transition using event.preventDefault(). I would recommend listening to $stateChangeStart in the run block of the module – this is far more elegant than using an application-wide controller encapsulating the entire app.

The above example solves the problem of displaying the modal from anywhere in the application. Some users expressed that this solution has some down sides, like unnaturally separating the modal display logic from the router configuration block. I couldn’t think of an elegant solution to this problem. If you see one, drop a line in the comments.

Angular Restmod: the better alternative to ng-resource

When building enterprise web apps it’s important to make some good design choices right in the beginning of the development process. One of those things is designing how your client application will communicate with your backend server. $http calls are simple to use, but when your application gets bigger, you will find it unwieldy. This is where REST APIs come in.

In AngularJS, ng-resource is the build-in way to communicate with REST APIs. If you haven’t tried it yet, I suggest you give it a shot. Working with RESTfull resources requires a different approach, but it’s well worth getting used to. The AngularJS Tutorial has a step on how to use ng-resource. This however is not the only module out there that lets you interact with your REST API. I have worked with these:

Recently however, I’ve found a new player - Angular Restmod. They’ve reached a stable 1.0 release number just a few days ago, and I’ve started using it in a project I’m working on for one of our clients.

Restmod tries to reach maximum compatibility with the JSON API standard, so it can extract your resources from specific JSON roots, read metadata from the meta root and use linked resources. This approach is working quite well for me thus far.

Read more...

About me

Hi there!

My name is Jacek Dargiel. I’m a JavaScript Developer from Warsaw, Poland. I work for 10Clouds - a major polish software house focused on web, mobile and design. I have five years of commercial Front-end Development experience, with some non-commercial projects earlier. I will not pretend to be an expert in anything. I do however love to learn and consume knowledge. I’m an enthusiast of shiny new technologies. Sometimes an evangelist even. I work with HTML5, CSS3, JS Web APIs, and more high-level frameworks like Angular and React.

This blog is my playground. You can read my thoughts on the technical aspects of the projects I work on at the moment, technologies I choose, and why. If you like what you read here, please subscribe to my feed and share links with your friends and co-workers. All the content you’ll find here is licensed under a Creative Commons license.

Oh, and find me on Front-end conferences in Warsaw and around Poland.

Have a splendid day!