Actualmente tengo una aplicación AngularJS con enrutamiento integrado. Funciona y todo está bien.
Mi archivo app.js se ve así:
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: '/' });
}]);
Mi aplicación tiene un CMS integrado donde puede copiar y agregar nuevos archivos html dentro del directorio / pages .
Me gustaría seguir pasando por el proveedor de enrutamiento, incluso para los nuevos archivos agregados dinámicamente.
En un mundo ideal, el patrón de enrutamiento sería:
$ routeProvider.when ( '/ nombre de la página ', {templateUrl: '/ pages / nombre de la página html', el controlador: CMSController});
Entonces, si mi nuevo nombre de página era "contact.html", me gustaría que angular seleccionara "/ contact" y lo redireccionara a "/pages/contact.html".
¿Es esto siquiera posible? y si es así, ¿cómo?
Actualizar
Ahora tengo esto en mi configuración de enrutamiento:
$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
y en mi CMSController:
function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
Esto establece el templateUrl actual en el valor correcto.
Sin embargo , ahora me gustaría cambiar la vista ng con el nuevo valor templateUrl. ¿Cómo se logra esto?
urlattr
se establece o se envía, me refiero a quéurlattr.name
producirá?Ok, lo resolvió.
Se agregó la solución a GitHub : http://gregorypratt.github.com/AngularDynamicRouting
En mi configuración de enrutamiento app.js:
$routeProvider.when('/pages/:name', { templateUrl: '/pages/home.html', controller: CMSController });
Luego, en mi controlador 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'];
Con #views siendo mi
<div id="views" ng-view></div>
Así que ahora funciona con enrutamiento estándar y enrutamiento dinámico.
Para probarlo, copié about.html lo llamé portfolio.html, cambié algunos de sus contenidos y entré
/#/pages/portfolio
en mi navegador y hey presto portfolio.html se mostró ....Actualizado Se agregó $ apply y $ compile al html para que se pueda inyectar contenido dinámico.
fuente
Creo que la forma más fácil de hacer tal cosa es resolver las rutas más tarde, podría preguntar las rutas a través de json, por ejemplo. Compruebe que hago una fábrica a partir de $ routeProvider durante la fase de configuración, a través de $ provide, para poder seguir usando el objeto $ routeProvider en la fase de ejecución, e incluso en los controladores.
'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(); }); });
fuente
$routeProvider
uso de alias para usar comofactory
(disponible despuésconfig
) no funcionará bien con la seguridad y la cohesión de la aplicación, de cualquier manera, técnica genial (¡voto a favor!).En los patrones de URI $ routeProvider, puede especificar parámetros variables, así:
$routeProvider.when('/page/:pageNumber' ...
y acceder a ellos en su controlador a través de $ routeParams.Hay un buen ejemplo al final de la página $ route: http://docs.angularjs.org/api/ng.$route
EDITAR (para la pregunta editada):
Desafortunadamente, el sistema de enrutamiento es muy limitado: hay mucha discusión sobre este tema y se han propuesto algunas soluciones, a saber, mediante la creación de múltiples vistas con nombre, etc. Pero en este momento, la directiva ngView solo sirve UNA vista por ruta, en una base uno a uno. Puede hacer esto de varias maneras: la más simple sería usar la plantilla de la vista como cargador, con una
<ng-include src="myTemplateUrl"></ng-include>
etiqueta en ella (se crearía $ scope.myTemplateUrl en el controlador).Utilizo una solución más compleja (pero más limpia, para problemas más grandes y complicados), básicamente omitiendo el servicio $ route por completo, que se detalla aquí:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
fuente
ng-include
metodo Es realmente simple y este es un enfoque mucho mejor que manipular el DOM.No estoy seguro de por qué esto funciona, pero las rutas dinámicas (o comodines si lo prefiere) son posibles en angular 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 -> carga "foo" parcial
example.com/bar-> carga "barra" parcial
No es necesario realizar ningún ajuste en la vista ng. El caso '/: a' es la única variable que he encontrado que logrará esto .. '/: foo' no funciona a menos que sus parciales sean todos foo1, foo2, etc. nombre.
Todos los valores activan el controlador dinámico, por lo que no hay "lo contrario", pero creo que es lo que está buscando en un escenario de enrutamiento dinámico o comodín.
fuente
A partir de AngularJS 1.1.3, ahora puede hacer exactamente lo que quiera usando el nuevo parámetro catch-all.
https://github.com/angular/angular.js/commit/7eafbb98c64c0dc079d7d3ec589f1270b7f6fea5
Desde el compromiso:
Lo he probado yo mismo (usando 1.1.5) y funciona muy bien. Solo tenga en cuenta que cada nueva URL recargará su controlador, por lo que para mantener cualquier tipo de estado, es posible que deba usar un servicio personalizado.
fuente
Aquí hay otra solución que funciona bien.
(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; } })();
fuente