AngularJS – UI-router – Как настроить динамические представления

Мне трудно найти любую документацию по использованию ui-router динамически через базу данных. Par для курса, все жестко закодировано.

Мой 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": "[email protected]", "templateUrl": "/app/views/content1.html"}, {"name" :"[email protected]", "templateUrl": "/app/views/left1.html" } ] }, { "name": "about", "url": "/about", "abstract": false, "parent": "root", "views": [ {"name": "[email protected]", "templateUrl": "/app/views/content2.html"}, {"name" :"[email protected]", "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 '[email protected]': { 'templateUrl': '/app/views/left1.html' }, '[email protected]': { 'templateUrl': '/app/views/container1.html' }, // third loop '[email protected]': { 'templateUrl': '/app/views/left2.html' }, '[email protected]': { 'templateUrl': '/app/views/container2.html' }, } }); }); $state.go("home"); }); }]); 

Я затрудняю динамически настраивать свои представления. Есть идеи?


ОБНОВИТЬ:

Я сделал ответ Plunker за Radim Köhler для всех, кого это интересует. Я ценю помощь.

Я думаю, что ui-router – это дефакто-маршрутизатор для углового и, будучи динамичным, облегчит управление большим приложением.

Существует плункер, показывающий, как мы можем динамически настраивать представления. Обновленная версия .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"); }); }]); 

Проверьте, что все в действии здесь

Я должен добавить улучшенную версию, ту, которая даже способна сделать больше.

Итак, теперь мы будем динамически загружать состояния – используя $http , json и определяем состояния в .run()

Но теперь мы можем перейти к любому динамическому состоянию с url (просто поместите его в адресную строку).

Магия встроена в UI-Router – см. Эту часть документа:

$ urlRouterProvider

deferIntercept(defer)

Отключает (или позволяет) отложить перехват изменения местоположения.

Если вы хотите настроить поведение синхронизации URL-адреса (например, если вы хотите отложить переход, но сохраните текущий URL-адрес) , вызовите этот метод во время настройки. Затем во время выполнения вызовите $urlRouter.listen() после того, как вы настроили свой собственный обработчик событий $ locationChangeSuccess.

Цитированный fragment:

 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(); }); 

Итак, обновленный плункер здесь . Теперь мы можем использовать даже .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(); }); }]); 

Проверьте обновленный плункер здесь

Я исследовал различные подходы к динамическим добавлениям маршрутов к ui.router .

Прежде всего, я нашел repositori с ngRouteProvider и основной идеей этого, разрешает $stateProvider и сохраняет его в закрытии на фазе .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); } 

SectionsFactory и MenuFactory являются обычными местами для декларирования / загрузки всех состояний.

Другая идея – просто использовать существующие угловые фазы приложения и расширять приложения приложения дополнительными провайдерами, что-то вроде:

 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-маршрутизатор Вложенное разрешение штата в дочерних штатах
  • Угловой - ui-router получает предыдущее состояние
  • Попытка динамически установить шаблонUrl в controllerе на основе константы
  • Как отправлять и извлекать параметры с помощью $ state.go toParams и $ stateParams?
  • Путают $ locationChangeSuccess и $ stateChangeStart
  • Angularjs ui-router абстрактное состояние с разрешением
  • Вложенные состояния или представления для макета с помощью leftbar в ui-router?
  • Разница между ui-sref и $ state.go в UL-маршрутизаторе AngularJS
  • Давайте будем гением компьютера.