Angular ui-router: ui-views vs directives?

AngularjsAngular UiAngular Ui-Router

Angularjs Problem Overview


The angular ui-router allows multiple nested views. The role of these interchangeable views seems to overlap the role of directives.

What are the pros/cons to using (multiple, nested) ui-views vs angular's directives?

UPDATE

States and routing are 2 different functions. States allow you to swap out partial.html templates and their controllers, and you can (optionally?) specify a corresponding URL/route.

In an email response from Tim Kindberg (a ui-router dev):

> ui-view is a directive, so if you use it you are using a directive > that has been worked on particular to work well with the rest of the > ui-router module. I can't imagine it being easy to roll your own > directive to replace this functionality.

And to this, it seems you could have 2 options:

Normal Directives:

app.directive('myDir1', {/*  controller: ... */})
   .directive('myDir2', {/*  controller: ... */}) 

vs ui-view "Directives"

$stateProvider.state('route1', {
     /*  url: "/route1", // optional?? */
      views: {
        "myDir1": { templateUrl: "myDir1.html" /* , controller: ... */ },
        "myDir2": { templateUrl: "myDir2.html" /* , controller: ... */ }
      }
    })

Bonus question:

Are normal angular directive features available to views? Such as:

  • Transclude
  • Replace
  • Isolate scoping
  • Compile / linking functions

If ui-views ARE directives, it seems clear their usage is different. Wouldn't it make sense to harmonize these models?

Angularjs Solutions


Solution 1 - Angularjs

How about if you used Angular UI router's inline views to point to directives?

Let's say you have a directive for a table that handles CRUD operations on user accounts. We'll say the directive is named user-admin. Our routes file would look like:

.state('users', {
  url: '/users',
  template: "<user-admin>"
});

This would give you many nice things:

  • Allow you to have a url that points straight to a directive
  • Removes the duplication of needing two templates (view template and directive template) when a state is just a directive
  • Allow you to start moving more controller logic into directives in prep for Angular 2.0. See here and here.

Solution 2 - Angularjs

After some thinking/ correspondence, here's my conclusion:

ui-views define containers, and states define what goes in those containers

When you put a ui-view='containerName' directive on an element, you're setting up a container that holds something. You haven't yet said anything about what goes in there.

When you create your $stateProvider.state(...) definitions, you're specifying what goes in these containers:

$stateProvider.state('someState', {
  views: {
    "containerName": { templateUrl: "someContents.html" /* , controller: ... */ },
    "container2": { templateUrl: "otherContents.html" /* , controller: ... */ }
  }
})

Can you use all the traditional directive functionality (transclude, replace, isolate scoping, compile/linking functions) with your ui-views? I'm not sure. For example:

$stateProvider.state('someState', {
  views: {
    "containerName": { 
              templateUrl: "someContents.html",
              scope: { localVar: "@" },  // can you
              transclude: true,          // do this?
              controller: function(){}
    },
    "container2": { templateUrl: "otherContents.html" /* , controller: ... */ }
  }
})

In conclusion, it seems like each option has its tradeoffs. Directives have some additional features, yet ui-views are interchangeable and can have routes associated.

Solution 3 - Angularjs

It seems you can do something like this with relative impunity:

    $stateProvider.state('general', {
        url: '/general',
        views: {
            main: {
                template: '<general-directive></general-directive>'
            }
        }
    });

Solution 4 - Angularjs

**In Config function:**
.state('list', {
        	url:'/list',
            template:'<user-info-table></user-info-table>',
            controller:'UserInfoTableController',
        });

**In Directive:**
angular.module('UserInfo').directive("userInfoTable", function() {
    return {
       templateUrl:'templates/UserInfoTable.html',
       restrict:'EA',
    };
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael LewisView Question on Stackoverflow
Solution 1 - AngularjsAaron GrayView Answer on Stackoverflow
Solution 2 - AngularjsMichael LewisView Answer on Stackoverflow
Solution 3 - AngularjsbtkView Answer on Stackoverflow
Solution 4 - AngularjsSurajView Answer on Stackoverflow