Obecnie mam aplikację AngularJS z wbudowanym routingiem. Działa i wszystko jest w porządku.
Mój plik app.js wygląda następująco:
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', { templateUrl: '/pages/home.html', controller: HomeController });
$routeProvider.when('/about', { templateUrl: '/pages/about.html', controller: AboutController });
$routeProvider.when('/privacy', { templateUrl: '/pages/privacy.html', controller: AboutController });
$routeProvider.when('/terms', { templateUrl: '/pages/terms.html', controller: AboutController });
$routeProvider.otherwise({ redirectTo: '/' });
}]);
Moja aplikacja ma wbudowany CMS, w którym możesz kopiować i dodawać nowe pliki html w katalogu / pages .
Chciałbym nadal przechodzić przez dostawcę routingu, chociaż nawet dla nowych dynamicznie dodawanych plików.
W idealnym świecie wzorzec routingu wyglądałby tak:
$ routeProvider.when ('/ nazwa strony ', {templateUrl: '/ strony / nazwa strony .html', kontroler: CMSController});
Jeśli więc moja nowa nazwa strony brzmiała „contact.html”, chciałbym, aby angular odebrał „/ contact” i przekierował do „/pages/contact.html”.
Czy to w ogóle możliwe ?! a jeśli tak, to jak ?!
Aktualizacja
Mam teraz to w mojej konfiguracji routingu:
$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
aw moim CMSController:
function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
Spowoduje to ustawienie bieżącego templateUrl na właściwą wartość.
Jednak chciałbym teraz zmienić widok ng z nową wartością templateUrl. Jak to się robi?
urlattr
jest ustawione lub wysłane, mam na myśli, courlattr.name
wyprodukuje?Ok, rozwiązałem to.
Dodano rozwiązanie do GitHub - http://gregorypratt.github.com/AngularDynamicRouting
W mojej konfiguracji routingu app.js:
$routeProvider.when('/pages/:name', { templateUrl: '/pages/home.html', controller: CMSController });
Następnie w moim kontrolerze CMS:
function CMSController($scope, $route, $routeParams) { $route.current.templateUrl = '/pages/' + $routeParams.name + ".html"; $.get($route.current.templateUrl, function (data) { $scope.$apply(function () { $('#views').html($compile(data)($scope)); }); }); ... } CMSController.$inject = ['$scope', '$route', '$routeParams'];
Z #views to my
<div id="views" ng-view></div>
Więc teraz działa z routingiem standardowym i routingiem dynamicznym.
Aby to przetestować, skopiowałem plik about.html nazwałem go portfolio.html, zmieniłem część jego zawartości i wprowadziłem
/#/pages/portfolio
do przeglądarki, a hej presto portfolio.html zostało wyświetlone ....Zaktualizowano Dodano $ Apply i $ compile do kodu HTML, aby można było wstrzyknąć zawartość dynamiczną.
źródło
Myślę, że najłatwiejszym sposobem na zrobienie tego jest rozwiązanie tras później, możesz na przykład zapytać o trasy przez json. Sprawdź, czy robię fabrykę z $ routeProvider podczas fazy konfiguracji, za pośrednictwem $ provider, dzięki czemu mogę nadal używać obiektu $ routeProvider w fazie uruchamiania, a nawet w kontrolerach.
'use strict'; angular.module('myapp', []).config(function($provide, $routeProvider) { $provide.factory('$routeProvider', function () { return $routeProvider; }); }).run(function($routeProvider, $http) { $routeProvider.when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }).otherwise({ redirectTo: '/' }); $http.get('/dynamic-routes.json').success(function(data) { $routeProvider.when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }); // you might need to call $route.reload() if the route changed $route.reload(); }); });
źródło
$routeProvider
używany jakofactory
(dostępny późniejconfig
) nie będzie dobrze współgrał z bezpieczeństwem i spójnością aplikacji - tak czy inaczej, fajna technika (upvote!).We wzorcach $ routeProvider URI możesz określić parametry zmiennych, na przykład:
$routeProvider.when('/page/:pageNumber' ...
i uzyskać do nich dostęp w kontrolerze za pośrednictwem $ routeParams.Dobry przykład znajduje się na końcu strony $ route: http://docs.angularjs.org/api/ng.$route
EDYCJA (dla edytowanego pytania):
System routingu jest niestety bardzo ograniczony - toczy się wiele dyskusji na ten temat, a niektóre rozwiązania zostały zaproponowane, mianowicie poprzez utworzenie wielu nazwanych widoków itp. Ale obecnie dyrektywa ngView obsługuje tylko JEDEN widok na trasę, na na zasadzie jeden do jednego. Możesz to zrobić na wiele sposobów - prostszym byłoby użycie szablonu widoku jako modułu ładującego, z
<ng-include src="myTemplateUrl"></ng-include>
tagiem w nim ($ scope.myTemplateUrl zostałby utworzony w kontrolerze).Używam bardziej złożonego (ale czystszego, dla większych i bardziej skomplikowanych problemów) rozwiązania, w zasadzie całkowicie pomijając usługę $ route, która jest szczegółowo opisana tutaj:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
źródło
ng-include
metodę. Jest to naprawdę proste i jest to znacznie lepsze podejście niż manipulowanie DOM.Nie wiem, dlaczego to działa, ale dynamiczne (lub wieloznaczne, jeśli wolisz) trasy są możliwe w kątowej 1.2.0-rc.2 ...
http://code.angularjs.org/1.2.0-rc.2/angular.min.js http://code.angularjs.org/1.2.0-rc.2/angular-route.min.js angular.module('yadda', [ 'ngRoute' ]). config(function ($routeProvider, $locationProvider) { $routeProvider. when('/:a', { template: '<div ng-include="templateUrl">Loading...</div>', controller: 'DynamicController' }). controller('DynamicController', function ($scope, $routeParams) { console.log($routeParams); $scope.templateUrl = 'partials/' + $routeParams.a; }).
example.com/foo -> ładuje część „foo”
example.com/bar-> ładuje część „bar”
Nie ma potrzeby dokonywania żadnych zmian w widoku ng. Przypadek '/: a' jest jedyną zmienną, jaką znalazłem, która to osiągnie .. '/: foo' nie działa, chyba że wszystkie twoje części składowe to foo1, foo2, etc ... '/: a' działa z dowolną podrzędną Nazwa.
Wszystkie wartości uruchamiają dynamiczny kontroler - więc nie ma „inaczej”, ale myślę, że właśnie tego szukasz w scenariuszu routingu dynamicznego lub wieloznacznego.
źródło
Począwszy od AngularJS 1.1.3, możesz teraz robić dokładnie to, co chcesz, używając nowego parametru catch-all.
https://github.com/angular/angular.js/commit/7eafbb98c64c0dc079d7d3ec589f1270b7f6fea5
Z zatwierdzenia:
Sam go przetestowałem (używając 1.1.5) i działa świetnie. Pamiętaj tylko, że każdy nowy adres URL przeładuje kontroler, więc aby zachować jakikolwiek stan, może być konieczne użycie usługi niestandardowej.
źródło
Oto inne rozwiązanie, które działa dobrze.
(function() { 'use strict'; angular.module('cms').config(route); route.$inject = ['$routeProvider']; function route($routeProvider) { $routeProvider .when('/:section', { templateUrl: buildPath }) .when('/:section/:page', { templateUrl: buildPath }) .when('/:section/:page/:task', { templateUrl: buildPath }); } function buildPath(path) { var layout = 'layout'; angular.forEach(path, function(value) { value = value.charAt(0).toUpperCase() + value.substring(1); layout += value; }); layout += '.tpl'; return 'client/app/layouts/' + layout; } })();
źródło