CodingCarlos / angular-demos

0 stars 2 forks source link

ui-router #3

Open CodingCarlos opened 7 years ago

CodingCarlos commented 7 years ago

ui.Router

When #2 ngRouter don't work right, or you need some views in the same page, there is a solution: ui.router. Full documentation is available in GitHub ui.Router Repository Wiki

This is, basically, another implementation of angular routes, but with a better performance, and lots of improvements.

The first step, is adding the script in your index.html,

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.0/angular-ui-router.js">

and the module in app.js

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

    .config(['$stateProvider', '$urlRouterProvider', 
        function($stateProvider, $urlRouterProvider) {

            $urlRouterProvider.otherwise('/');

            $stateProvider
                .state('name', {
                    url: "/",
                    template: "<h3>hello world!</h3>"
                })
                .state('search', {
                    url: "/red",
                    templateUrl: "views/search.html"
                })
        }
    ]);

As you see, is quite similar to #2 ngRouter but with some words changed.

Both templating is the same. You can also add controllers, or variables in the same way you used to did in #2 ngRouter.

The index.html that contains the views would seem something like this:

<body ng-app="app">
    <ui-view></ui-view>
</body>

In your views, the linkgs don't have to had the href param, but a brand new ui-sref="viewName"

Go to Red

In case you have some params in your url, like variables, you can pass the params in your view on this way:

<a ui-sref="color( {name: 'red'} )">Go to Red</a>

or if you need it to be a variable, just do this:

<input type="text" ng-model="colorName">
<a ui-sref="color( {name: colorName} )">Go to {{colorName}}</a>

In case you add variables, in your controller you no longer have $routeParams, but $stateParams. Will be exactly the same:

controller.js

angular.module('app').controller("DemoController", DemoController);

function DemoController($stateParams) {
    var self = this;
    self.name = $stateParams.name;
}

More views

If you need more than one view per state, working with each own controller, just add it like this:

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

    .config(['$stateProvider', '$urlRouterProvider', 
        function($stateProvider, $urlRouterProvider) {

            $urlRouterProvider.otherwise('/');

            $stateProvider
                .state('home', {
                    url: "/",
                    views: {
                        "topbar": { 
                            templateUrl: "views/topbar-home.html" 
                        },
                        "content": { 
                            templateUrl: "views/home.html",
                            controller: "HomeController",
                            controllerAs: "Home"
                        }
                    }
                })
                .state('search', {
                    url: "/red",
                    views: {
                        "topbar": { 
                            templateUrl: "views/topbar-red.html" 
                        },
                        "content": { 
                            templateUrl: "views/red.html",
                            controller: "RedController",
                            controllerAs: "Red"
                        }
                    }
                })
        }
    ]);

This views are defined in your html:

<body ng-app="app">
    <div ui-view="topbar"></div>
    <div ui-view="content"></div>
</body>

Nesting views

Full documentation

Each state can also have a child states, For example, a "user" state might have a child "user.edit".

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

    .config(['$stateProvider', '$urlRouterProvider', 
        function($stateProvider, $urlRouterProvider) {

            $urlRouterProvider.otherwise('/');

            $stateProvider
                .state('user', {
                    url: "/user",
                    views: {
                        "topbar": { 
                            templateUrl: "views/topbar.html" 
                        },
                        "content": { 
                            templateUrl: "views/user..html",
                            controller: "UserController",
                            controllerAs: "User"
                        }
                    }
                })
                .state('user.edit', {
                    parent: "user"
                    url: "/edit",
                    views: {
                        "user@edit": { 
                            templateUrl: "views/user-edit.html",
                            controller: "EditController",
                            controllerAs: "Edit"
                        }
                    }
                })
        }
    ]);

index.html

<body ng-app="app">
    <div ui-view="topbar"></div>
    <div ui-view="content"></div>
</body>

user.html

<div>
    <!-- Here goes the code of user view -->
    <div ui-view="edit"></div>
</div>
CodingCarlos commented 7 years ago

As we had a in-class issue with abstract states, I'm documenting it here:

Abstract states

Any state can be acessible, or abstract. Imagine your basic interface, a topbar, a bottombar, and maybe a sidebar. It is the same in all the pages, so, might have sense to have a parent with all that views setted, to avoid repainting in every state change. So, here you have an abstract state.

This mean:

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

    .config(['$stateProvider', '$urlRouterProvider', 
        function($stateProvider, $urlRouterProvider) {

            $urlRouterProvider.otherwise('/');

            $stateProvider
                .state('root', {
                    abstract: true,
                    views: {
                        "topbar": { 
                            templateUrl: "views/topbar.html" 
                        },
                        "bottombar": { 
                            templateUrl: "views/bottombar..html",
                            controller: "BottomController",
                            controllerAs: "Bottom"
                        }
                    }
                })
                .state('home', {
                    parent: "root"
                    url: "/",
                    views: {
                        "root@content": { 
                            templateUrl: "views/user-edit.html",
                            controller: "EditController",
                            controllerAs: "Edit"
                        }
                    }
                })
        }
    ]);

and in your index:

<body ng-app="app">
    <div ui-view="topbar"></div>
    <div ui-view="content"></div>
</body>

We had some issues calling the parent views. There was a naming problem, so here is the guide of view naming.