AngularJS UI router named views lazy loading

删除回忆录丶 提交于 2019-12-22 08:37:21

问题


AngularJS UI router named views loading based on user access rather than loading at the time of state route access.

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 above example, when a user accesses the state main the UI-router loads all the named views html from server.

Question:

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

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

回答1:


If you are looking to load your tab content dynamically from template urls based on the value of tabs available to the user as defined in $scope.tabs, you should consider using a simple directive rather than ui-router views.

As you have already discovered ui-router will try and load the subviews regardless of whether they are referenced in the main view for that state.

We can however use our own directive to load templates, and therefore because the directive only runs when present in the main view, the templates load on demand.

template Directive:

We create a template directive, that allows us to pull in a template into an html element.

.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 the $http service to get the template from the server. Then it uses the $compile service to apply the scope to the angular template, and renders it into the target element.

Usage:

Update the format of your main tabs template as below. Note we no longer reference ui-view, instead we call our template directive passing in the url we want to load in the div. With the current content of the div being the loading indicator.

(If the controller attribute is set the template will be wrapped with an <span> having the ng-controller attribute, so a template controller can be applied. 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 puts the code given 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>

I hope this helps. If you have questions about something just ask.



来源:https://stackoverflow.com/questions/30111594/angularjs-ui-router-named-views-lazy-loading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!