AngularJS - UI路由器 - 如何配置动态视图AngularJS - UI路由器

2019-05-09 06:55发布

我有困难找上动态地利用UI路由器通过数据库的任何文件。 意料之中的事,一切都硬编码。

我的JSON:

[
   {
       "name": "root",
       "url": "/",
       "parent": "",
       "abstract": true,
       "views": [
            {"name": "header", "templateUrl": "/app/views/header.html"},            
            {"name" :"footer", "templateUrl": "/app/views/footer.html" }
       ]
   },
    {
        "name": "home",
        "url": "",
        "abstract" : false,
        "parent": "root",
        "views": [
            {"name": "container@", "templateUrl": "/app/views/content1.html"},            
            {"name" :"left@", "templateUrl": "/app/views/left1.html" }
       ]
    },
    {
        "name": "about",
        "url": "/about",
        "abstract": false,
        "parent": "root",
        "views": [
             {"name": "container@", "templateUrl": "/app/views/content2.html"},            
             {"name" :"left@", "templateUrl": "/app/views/left2.html" }
            ]
    }
]

我的应用程序:

'use strict';

var $stateProviderRef = null;
var $urlRouterProviderRef = null;

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


 app.factory('menuItems', function ($http) {
    return {
      all: function () {
        return $http({
            url: '/app/jsonData/efstates.js',
            method: 'GET'
        });
    }
  };
 });


  app.config(function ($locationProvider, $urlRouterProvider, $stateProvider) {
    $urlRouterProviderRef = $urlRouterProvider;
    $stateProviderRef = $stateProvider;
    $locationProvider.html5Mode(false);
    $urlRouterProviderRef.otherwise("/");
  });


  app.run(['$q', '$rootScope', '$state', 'menuItems',
  function ($q, $rootScope, $state, menuItems) {
      menuItems.all().success(function (data) {
          angular.forEach(data, function (value, key) {                
              $stateProviderRef.state(name = value.name, {
                  "url": value.url,
                  "parent" : value.parent,
                  "abstract": value.abstract,
                  "views": {
                     // do not want the below hard coded, I want to loop
                     // through the respective json array objects and populate state & views 
                     // I can do this with everything but views.

                     // first loop
                     'header': { 'templateUrl': '/app/views/header.html' },
                     'footer': { 'templateUrl': '/app/views/footer.html' },

                     // second loop
                     'left@':  { 'templateUrl': '/app/views/left1.html' },
                     'container@': { 'templateUrl': '/app/views/container1.html' },

                     // third loop
                     'left@':  { 'templateUrl': '/app/views/left2.html' },
                     'container@': { 'templateUrl': '/app/views/container2.html' },
                }
            });
        });
        $state.go("home");
    });
 }]);

我有困难动态地配置自己的看法。 有任何想法吗?


更新:

我做了一个Plunker每拉迪姆·克勒的回答兴趣的人。 我欣赏的帮助。

我觉得UI路由器是角和富有活力就会使大量的应用程序更易于管理事实上的路由器。

Answer 1:

有一个plunker展示我们如何能够动态配置的意见。 该更新版本.run()会是这样的:

app.run(['$q', '$rootScope', '$state', '$http',
  function ($q, $rootScope, $state, $http) 
  {
    $http.get("myJson.json")
    .success(function(data)
    {
      angular.forEach(data, function (value, key) 
      { 
          var state = {
            "url": value.url,
            "parent" : value.parent,
            "abstract": value.abstract,
            "views": {}
          };

          // here we configure the views
          angular.forEach(value.views, function (view) 
          {
            state.views[view.name] = {
              templateUrl : view.templateUrl,
            };
          });

          $stateProviderRef.state(value.name, state);
      });
      $state.go("home");    
    });
}]);

检查所有的行动在这里



Answer 2:

我要追加一个改进的版本,其中一个甚至能做得更多。

所以,现在我们还是会负荷状态动态-使用$httpjson和定义状态.run()

但是现在我们可以导航URL的动态状态 (只是把它放在地址栏)。

神奇的是内置到用户界面,路由器 - 看到文档的这一部分:

$ urlRouterProvider

deferIntercept(defer)

禁用或有助延缓位置变化拦截。

如果您想自定义(,例如,如果你想推迟一个过渡,但保持当前的URL)同步URL的行为,呼吁在配置时此方法。 然后,在运行时,调用$urlRouter.listen()你已经配置了自己的$ locationChangeSuccess事件处理程序后。

引片段:

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

app.config(function($urlRouterProvider) {

  // Prevent $urlRouter from automatically intercepting URL changes;
  // this allows you to configure custom behavior in between
  // location changes and route synchronization:
  $urlRouterProvider.deferIntercept();

}).run(function($rootScope, $urlRouter, UserService) {

  $rootScope.$on('$locationChangeSuccess', function(e) {
    // UserService is an example service for managing user state
    if (UserService.isLoggedIn()) return;

    // Prevent $urlRouter's default handler from firing
    e.preventDefault();

    UserService.handleLogin().then(function() {
      // Once the user has logged in, sync the current URL
      // to the router:
      $urlRouter.sync();
    });
  });

  // Configures $urlRouter's listener *after* your custom listener
  $urlRouter.listen();
});

因此, 更新plunker在这里 。 我们现在可以使用连.otherwise()导航到最近定义的状态,或者通过URL去那里:

所述.config()

app.config(function ($locationProvider, $urlRouterProvider, $stateProvider) {

    // Prevent $urlRouter from automatically intercepting URL changes;
    // this allows you to configure custom behavior in between
    // location changes and route synchronization:
    $urlRouterProvider.deferIntercept();
    $urlRouterProvider.otherwise('/other');

    $locationProvider.html5Mode({enabled: false});
    $stateProviderRef = $stateProvider;
});

所述.run()

app.run(['$q', '$rootScope','$http', '$urlRouter',
  function ($q, $rootScope, $http, $urlRouter) 
  {
    $http
      .get("myJson.json")
      .success(function(data)
      {
        angular.forEach(data, function (value, key) 
        { 
          var state = {
            "url": value.url,
            "parent" : value.parent,
            "abstract": value.abstract,
            "views": {}
          };

          angular.forEach(value.views, function (view) 
          {
            state.views[view.name] = {
              templateUrl : view.templateUrl,
            };
          });

          $stateProviderRef.state(value.name, state);
        });
        // Configures $urlRouter's listener *after* your custom listener            
        $urlRouter.sync();
        $urlRouter.listen();
      });
}]);

检查这里更新plunker



Answer 3:

我已经研究了动态添加路由到不同的方法ui.router

首先,我发现repositori与ngRouteProvider和它的主要思想,是解决$stateProvider ANS其保存在关闭上.config相,然后用这个REFFERENCE在其他任何时间,在飞行中增加新的击溃。 这是好主意,它可以得到改善。 我认为,更好的办法是划分为节能提供参考,在任何行吟诗人的时间和地点操纵他们的责任。 请看例子refsProvider

angular
    .module('app.common', [])
        .provider('refs', ReferencesProvider);

const refs = {};

function ReferencesProvider() {
    this.$get = function () {
        return {
            get: function (name) {
              return refs[name];
        }
    };
};

this.injectRef = function (name, ref) {
        refs[name] = ref;
    };
}

使用refsProvider

angular.module('app', [
    'ui.router',
    'app.common',
    'app.side-menu',
])
    .config(AppRouts)
    .run(AppRun);

AppRouts.$inject = ['$stateProvider', '$urlRouterProvider', 'refsProvider'];

function AppRouts($stateProvider, $urlRouterProvider, refsProvider) {
    $urlRouterProvider.otherwise('/sign-in');
    $stateProvider
        .state('login', {
            url: '/sign-in',
            templateUrl: 'tpl/auth/sign-in.html',
            controller: 'AuthCtrl as vm'
        })
        .state('register', {
            url: '/register',
            templateUrl: 'tpl/auth/register.html',
            controller: 'AuthCtrl as vm'
        });

    refsProvider.injectRef('$urlRouterProvider', $urlRouterProvider);
    refsProvider.injectRef('$stateProvider', $stateProvider);

}

AppRun.$inject = ['SectionsFactory', 'MenuFactory', 'refs'];

function AppRun(sectionsFactory, menuFactory, refs) {
    let $stateProvider = refs.get('$stateProvider');
    // adding new states from different places
    sectionsFactory.extendStates($stateProvider);
    menuFactory.extendStates($stateProvider);
}

SectionsFactoryMenuFactory是申报常见的地方/加载所有状态。

它只是使用存在角应用阶段,并通过额外的提供者,像延长应用程序状态的其他想法:

angular.module('app.side-menu', []);
    .provider('SideMenu', SideMenuProvider);

let menuItems = [
    {
        label: 'Home',
        active: false,
        icon: 'svg-side-menu-home',
        url: '/app',
        state: 'app',
        templateUrl: 'tpl/home/dasboard.html',
        controller: 'HomeCtrl'
    }, {
        label: 'Charts',
        active: false,
        icon: 'svg-side-menu-chart-pie',
        url: '/charts',
        state: 'charts',
        templateUrl: 'tpl/charts/main-charts.html'
    }, {
        label: 'Settings',
        active: false,
        icon: 'svg-side-menu-settings',
        url: '/'
    }
];
const defaultExistState = menuItems[0].state;

function SideMenuProvider() {
    this.$get = function () {
        return {
            get items() {
                return menuItems;
            }
        };
    };
    this.extendStates = ExtendStates;
}

function ExtendStates($stateProvider) {
    menuItems.forEach(function (item) {
        if (item.state) {
            let stateObj = {
                url: item.url,
                templateUrl: item.templateUrl,
                controllerAs: 'vm'
            };
            if (item.controller) {
                stateObj.controller = `${item.controller} as vm`;
            }
            $stateProvider.state(item.state, stateObj);
        } else {
            item.state = defaultExistState;
        }
    });
}

在这种情况下,我们没有必要使用.run阶段extenfing状态,并AppRouts从上面的例子中,将改为:

AppRouts.$inject = ['$stateProvider', '$urlRouterProvider', 'SideMenuProvider'];

function AppRouts($stateProvider, $urlRouterProvider, SideMenuProvider) {
    $urlRouterProvider.otherwise('/sign-in');
    $stateProvider
        .state('login', {
            url: '/sign-in',
            templateUrl: 'tpl/auth/sign-in.html',
            controller: 'AuthCtrl as vm'
        })
        .state('register', {
            url: '/register',
            templateUrl: 'tpl/auth/register.html',
            controller: 'AuthCtrl as vm'
        })

    SideMenuProvider.extendStates($stateProvider);
}

此外,我们还可以使用在任何地方的所有菜单项: SideMenu.items



文章来源: AngularJS - UI-router - How to configure dynamic views