How to Write Modular Code with Angular UI-Router & Named Views

Share this article

Key Takeaways

  • Angular UI Router is a powerful tool for managing different states in complex web applications, providing more control over each view compared to the native AngularJS routing implementation. It uses dot-notation to define child states within a parent state and absolute names to control where specific pieces of a web app are displayed, enabling a modular application design.
  • The UI Router allows developers to define a views object inside of $stateProvider, which is used to define the names of the views and the paths of their templates. Unnamed views target the parent state, a concept known as relative naming. Named views use the @ syntax to map components to a specific state, a concept known as absolute naming.
  • Absolute naming makes code extremely modular, allowing developers to reuse templates throughout an application or in future projects. It also simplifies the use of different components of a web application, such as headers and footers, for specific views, saving time and effort.

One of the most important concepts in web development is writing clean, modular code. This is especially relevant when working as part of a team on highly complex applications. The Angular framework was built to create high-level applications, which can become very complex very fast, which in turn makes writing modular code all the more vital. One of the tools that can aid you greatly in this quest is the Angular UI Router, which was built to help manage different states of your web app. In contrast to the native AngularJS routing implementation, it gives you complete control over each of its views.

If you have used ui-router before, you may be aware of how the dot-notation is used to define child states inside of a parent state. You may not, however, be aware of how the ui-router library deals with named views nested inside of a parent state. And this is what I am going to explain today.

I am going to show you how ui-router uses absolute names to give you complete control over where specific pieces of a web app are displayed. This allows you to easily add and remove different pieces of the interface in order to make a modular application, built up of different components. Specifically, I am going to show you how to map a navigation bar, some body content, and a footer, to a specific state. As ever, the code for this tutorial can be found on GitHub and you can also find a demo at the end of the article.

Getting Started

Take a minute to navigate through the files that make up this demo (available at the GitHub link above). You can see we have an index.html file where we include AngularJS, as well as the library for the ui-router. In this file we also have two ui-view directives into which we will insert our content. Next we have an app.js file, which will contain the code for our Angular app, and a templates directory. This directory will be used to house all of our different views. Although this folder is not necessary, it is definitely in your best interest to use some sort of structure when building applications with Angular. As you can see, I have included an assets folder inside of the templates folder. This is where I like to keep my reusable components: headers, navbars, footers, etc. I figured you may find this convention helpful as it keeps your code extremely modular.

UI-Router

Add a Dependency to ui-router

Let’s begin configuring our application. Inside of our app.js file, we need to add a dependency on the ui-router to our main angular module.

angular.module('app', ['ui.router'])

Configuring Our Routes

Once that is done, we can move on to our application’s config object. Here, we will be dealing with $stateProvider and $urlRouterProvider, so we need to inject them into our config object in order to have them available.

Next we want to pass the URL of our home state into $urlRouterProvider.otherwise(), so it maps our application to this state by default. We will then need to use $stateProvider, which is what we will be dealing with for the rest of the tutorial. $stateProvider is what ui-router gives developers to use when routing applications. A state corresponds to a “place” in the application in terms of the overall UI and navigation. A state describes what the UI looks like and what it does at that place. It works in the same way that ngRoute uses routeProvider.

Below is a how the app.js file should look at this moment. Once we have configured the urlRouterProvider, we utilize $stateProvider to define the different states of the application. In this instance, we are defining a state named home, and only the URL is configured.

angular.module('app', ['ui.router'])
  .config(['$stateProvider', '$urlRouterProvider', 
    function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise('/');
      $stateProvider
      .state('home', {
        url: '/'
      });
    }
  ]);

The Views Object

Now that you have the bare-bones set up, you need to define a views object inside of $stateProvider. It should be placed immediately following the home state’s URL. Inside this object is where we are going to define the names of our views, as well as the paths of their templates. Here you can also define things such as controllers; however, I have passed over that for the sake of brevity in this tutorial.

Moving on, we must first create and define an unnamed view that will target the parent state — which in this case is home. The templateUrl of this unnamed view will essentially tie the two together. This is known as relative naming and tells angular to insert this unnamed view in the <div ui-view> inside our index.html file. Your code should now replicate the app.js below.

angular.module('app', ['ui.router'])
  .config(['$stateProvider', '$urlRouterProvider', 
    function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise('/');
      $stateProvider
        .state('home', {
          url: '/',
          views: {
            '': { 
              templateUrl: './templates/main.html' 
            },
          }
        });
     }
   ]);

As you can see, the unnamed view resolves to main.html, which should resemble the code below.

<div ui-view="nav"></div>
<h1 class="text-center">This content is in main.html</h1>
<div ui-view="body"></div>
<div ui-view="footer"></div>

The file main.html includes three named views – nav, body, and footer. In order for these components to appear under the home state, we must define them using absolute naming. Specifically, we must use the @ syntax to tell AngularJS that these components of our application should be mapped to a specific state. This follows the viewName@stateName syntax and tells our application to utilize named views from an absolute, or specific state. You can read more about relative vs. absolute names here.

You will see @home used throughout our config object, to ensure that Angular knows our named views target our home state. If these absolute names are not present, the application will not know where to find these named views. That said, take a look below and see how the application should be routed.

angular.module('app', ['ui.router'])
  .config(['$stateProvider', '$urlRouterProvider', 
    function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise('/');
      $stateProvider
        .state('home', {
          url: '/',
          views: {
            '': { templateUrl: './templates/main.html'},
            'nav@home': { templateUrl: './templates/assets/nav.html' },
            'body@home': { templateUrl: './templates/body.html'},
            'footer@home': { templateUrl: './templates/assets/footer.html' }
         }
      });
    }
  ]);

And this is what we end up with:

See the Pen How to Write Modular Code with Angular UI-Router & Named Views by SitePoint (@SitePoint) on CodePen.

Why This Is Great

As I said earlier, absolute naming makes your code extremely modular. In this tutorial, I placed all of our views inside of a templates folder. However, you can take this a step further and create folders for the different views of your applications. This allows you to reuse templates throughout your application, as well as in future projects! The ui-router library makes it extremely easy to use different components of a web application, such as header and footers for specific views. This will make it easier to reuse code throughout different projects, and can definitely save you time.

Conclusion

There is much more complex, high-level nesting you can do with absolute names — this was only one example! Nonetheless, I hope you gained a deeper perspective of some of the things that ui-router makes possible. In this article written by Antonio Morales, he does an extremely good job of explaining the differences between absolute and relative naming, child states, and other aspects of Angular’s ui-router library. As always, let me know if you have any questions regarding this tutorial. I would be happy to answer them.

Frequently Asked Questions on Writing Modular Code with Angular UI Router and Named Views

What is Angular UI Router and how does it differ from the standard Angular Router?

Angular UI Router is a flexible routing framework for AngularJS, providing functionalities that are not available in the standard Angular Router. It allows for nested views and multiple named views, unlike the standard Angular Router which only supports one view per URL. This makes Angular UI Router a powerful tool for building complex, large-scale applications.

How do I set up Angular UI Router in my project?

To set up Angular UI Router, you first need to include the Angular UI Router script in your HTML file. Then, you need to add ‘ui.router’ as a module dependency in your AngularJS application. After that, you can configure your states using the $stateProvider and set the default state using the $urlRouterProvider.

What are named views in Angular UI Router and how do I use them?

Named views are a feature of Angular UI Router that allows you to assign names to your views. This enables you to have multiple views per URL, which can be very useful in complex applications. To use named views, you need to include the ‘ui-view’ directive in your HTML file and assign a name to it. Then, you can reference this name in your state configuration.

How do I navigate between states in Angular UI Router?

You can navigate between states in Angular UI Router using the $state.go() method. This method takes the name of the state as a parameter and optionally, an object of parameters for the state. You can also use the ui-sref directive in your HTML file to create links to states.

How do I pass parameters to states in Angular UI Router?

You can pass parameters to states in Angular UI Router by including them in the state configuration. You can then access these parameters in your controllers using the $stateParams service.

How do I handle state changes in Angular UI Router?

You can handle state changes in Angular UI Router using the $stateChangeStart and $stateChangeSuccess events. These events are broadcasted on the $rootScope and can be listened to in your controllers.

How do I resolve data before a state is activated in Angular UI Router?

You can resolve data before a state is activated in Angular UI Router using the resolve property in the state configuration. This property is an object that defines any dependencies that need to be resolved before the state is activated.

How do I handle errors in Angular UI Router?

You can handle errors in Angular UI Router using the $stateChangeError event. This event is broadcasted on the $rootScope and can be listened to in your controllers.

How do I use nested views in Angular UI Router?

You can use nested views in Angular UI Router by including the ‘ui-view’ directive in your HTML file and assigning a name to it. Then, you can reference this name in your state configuration.

How do I use multiple named views in Angular UI Router?

You can use multiple named views in Angular UI Router by including the ‘ui-view’ directive in your HTML file and assigning different names to them. Then, you can reference these names in your state configuration.

Thomas GrecoThomas Greco
View Author

Thomas Greco is a web developer based out of New York City specializing in full-stack development with the M.E.A.N. stack technologies. Before web development, Thomas worked as a graphic designer, and he continues to utilize his background in design when building web applications. Have a question for Thomas ? You can reach him on Twitter.

jameshLearn Angularroutesrouting
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week