59

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?

Community
  • 1
  • 1
Michael Lewis
  • 4,252
  • 6
  • 28
  • 39
  • 5
    Upvoting - hasn't been answered yet. I just logged in SO to ask the exact same question as clearly directives and views of ui-router are overlapping one-another. I have two parts of my application: navigation,content which I've placed in two directives. Inside the navigation partial, I use ui-sref links to states. How do I go about changing my content, which is an angular.directive, with a ui-router view. It's all a bit fuzzy around the edges. – George Katsanos Sep 14 '14 at 21:36

4 Answers4

37

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.
Aaron Gray
  • 11,283
  • 7
  • 55
  • 61
  • So you would do something like this: this.basicModule.directive(constants.valutaDirectiveName, valutaDirective.ValutaDirective.Factory()); and then you would compose the state like this: this.basicModule.config(["$stateProvider", ($stateProvider:angular.ui.IStateProvider):void=> { $stateProvider.state("ValutaScreen", { url: "/ValutaScreen", template: "<" + constants.valutaDirectiveName + ">" }); }]); ? – Franz1986 Jul 28 '15 at 13:34
  • 1
    Trying to follow this pattern how do you handle a [directive within a state view](http://codepen.io/absynce/pen/waVRew)? In that example the Home content is initially loaded underneath the header. I'm guessing it's a timing issue with switching to the directive. However I can't figure out a clean way around it. – absynce Aug 25 '15 at 22:44
  • In how many cases do we encounter a full template as a directive? And directives when used for partial views already have a parent template. Nice feature to list but doesn't seems practically usable or convinces to use and include ui-router in my project file. – HalfWebDev Jul 10 '16 at 05:38
7

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.

Michael Lewis
  • 4,252
  • 6
  • 28
  • 39
  • 1
    If anyone's here, I tried `transclude: true` with `ng-transclude`, and it threw an error – Michael Lewis Apr 01 '14 at 21:34
  • 1
    Are the ui-views interchangeable if you have to define the template and controller in the state? I have this same question but I'm thinking, without some way to swap out what goes in those views, it's no different than directives. As you say, it even seems directives are more powerful. – Joao Oct 21 '14 at 20:18
  • @Joao you can specify both the controller and template of a state as functions which dynamically return appropriate controllers and templates. So yes you can swap out the content. However, there are downsides, IMHO to the maintainability of such code. – Aluan Haddad Dec 19 '15 at 03:11
5

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

    $stateProvider.state('general', {
        url: '/general',
        views: {
            main: {
                template: '<general-directive></general-directive>'
            }
        }
    });
btk
  • 3,158
  • 2
  • 29
  • 30
0
**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',
    };
});
Suraj
  • 1