AngularJS UI router named views lazy loading

AngularJS UI Router named loading view based on user access, not loading while accessing the state route.

Example:

$stateProvider
.state("login",
{
    url: "/login",
    templateUrl: getTemplateUrl("login/Index")
})    
.state("main",
{
    url: "/main",
    views: 
    {
        '': { templateUrl: getTemplateUrl('home/shell') },
        'test1@main': { templateUrl: 'home/test1' },
        'test2@main': { templateUrl: 'home/test2' },
        'test3@main': { templateUrl:  getTemplateUrl('home/test3') }                     
    }
});

      

In the example above, when the user accesses the state main

, the UI router downloads all named html views from the server.

Question:

Can we load named-views when required below? I mean whenever we add a new tab dynamically and then only load the respectable html view from the server.

<tab ng-repeat="tab in tabs">    
    <div>     
        <div ui-view='{{tab.view}}'></div>
    </div>
 </tab>

      

+3


source to share


1 answer


If you want to dynamically load the contents of a tab from templated URLs based on the tab values ​​available to the user as defined in $scope.tabs

, you should consider using a simple directive rather than the ui-router look.

As you already found out, ui-router will try to load subrequests, regardless of whether they refer to the main view of this state.

However, we can use our own directive to load templates, and because the directive only works when present in the main view, templates are loaded on demand.

template

Directive:

We create a directive template

that allows us to insert a template into an element html

.

.directive('template', ['$compile', '$http', function($compile, $http) {
    return {
        restrict: 'A',
        replace: false,
        link: function($scope, element, attrs) {
            var template = attrs['template'];
            var controller = attrs['controller'];
            if(template!==undefined){
                // Load the template
                $http.get(template).success(function(html){
                    // Set the template
                    var e = angular.element(controller === undefined || controller.length === 0 ? html : "<span ng-controller='" + controller + "'>" + html + "</span>");
                    var compiled = $compile(e);
                    element.html(e);
                    compiled($scope);
                });
            }
        }
    };
}]);

      

So this code uses a service $http

to get the template from the server. Then it uses the service $compile

to apply the scope to the angular template and renders it to the target element.

Using:

Update the format of the main tab template as shown below. Note that we are not referencing anymore ui-view

, instead we name our directive template

passing in url

that we want to load in div

. If the current content div

is a loading indicator.

(If the attribute is set controller

, the template will be wrapped with an <span>

attribute ng-controller

, so a templated controller can be used. This is optional.)



in home/shell

:

<tab ng-repeat="(tabName,tab) in tabs">
    <div template='{{tab.template}}' controller="{{tab.controller}}">Loading {{tabName}} ...</div>
 </tab>

      

Then set the tabs you want to display:

$scope.tabs = {
    'tab1': { template: 'home/tab1'},
    'tab2': { template: 'home/tab2', controller: 'Tab2Controller' },
    'tab3': { template: 'home/tab3'}
};

      


Full source:

This just adds the code above as an example AngularJS app. Assumes the template paths are valid, i.e. home/shell

, home/tab1

etc.

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
    <meta charset="utf-8">
    <title>Angular Views</title>
</head>
<body ng-app="myTabbedApp">
    <div ui-view></div>
    <script>
        angular.module('myTabbedApp', ['ui.router'])

            /* Controller for the Main page ie. home/shell */
            .controller('MainPageTabController', ['$scope', function($scope) {
                // Set the page tabs dynamically as required by your code
                $scope.tabs = {
                    'tab1': { template: 'home/tab1'},
                    'tab2': { template: 'home/tab2', controller: 'Tab2Controller' },
                    'tab3': { template: 'home/tab3'}
                };
            }])

            /* Example controller for Tab 2 */
            .controller('Tab2Controller', ['$scope', function($scope) {
                $scope.hello = "world";
            }])

            /* State provider for ui router */
            .config(['$stateProvider', function($stateProvider){
                $stateProvider
                    .state("login",
                    {
                        url: "/login",
                        templateUrl: "login/index"
                    })
                    .state("main",
                    {
                        url: "/main",
                        templateUrl: 'home/shell',
                        controller: 'MainPageTabController'
                    });
            }])

            /* Directive to load templates dynamically */
            .directive('template', ['$compile', '$http', function($compile, $http) {
                return {
                    restrict: 'A',
                    replace: false,
                    link: function($scope, element, attrs) {
                        var template = attrs['template'];
                        if(template!==undefined){
                            // Load the template
                            $http.get(template).success(function(html){
                                // Set the template
                                var e = angular.element(html);
                                var compiled = $compile(e);
                                element.html(e);
                                compiled($scope);
                            });
                        }
                    }
                };
            }]);
    </script>
</body>
</html>

      

Hope this helps. If you have questions about something, just ask.

+4


source







All Articles