J'ai actuellement une application AngularJS avec routage intégré. Cela fonctionne et tout va bien.
Mon fichier app.js ressemble à ceci:
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: '/' });
}]);
Mon application a un CMS intégré dans lequel vous pouvez copier et ajouter de nouveaux fichiers HTML dans le répertoire / pages.
J'aimerais quand même passer par le fournisseur de routage même pour les nouveaux fichiers ajoutés dynamiquement.
Dans un monde idéal, le modèle de routage serait:
$ routeProvider.when ('/ pagename', {templateUrl: '/pages/pagename.html', contrôleur: CMSController});
Donc, si mon nouveau nom de page était "contact.html", je voudrais que angular récupère "/ contact" et redirige vers "/pages/contact.html".
Est-ce seulement possible?! et si oui comment?!
Mise à jour
J'ai maintenant ceci dans ma configuration de routage:
$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
et dans mon CMSController:
function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
Ceci définit le templateUrl actuel sur la bonne valeur.
Cependant je voudrais maintenant changer le ng-view avec le nouveau valeur templateUrl. Comment est-ce accompli?
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/page/:name*', {
templateUrl: function(urlattr){
return '/pages/' + urlattr.name + '.html';
},
controller: 'CMSController'
});
}
]);
À partir de la documentation (1.3.0):
"Si templateUrl est une fonction, elle sera appelée avec les paramètres suivants:
{Tableau.} - Paramètres de route extraits de la $ location.path () actuelle en appliquant la route actuelle "
Aussi
when (path, route): Méthode
- path peut contenir des groupes nommés commençant par un signe deux-points et se terminant par une étoile: par exemple: nom*. Tous les caractères sont stockés dans $ routeParams sous le nom indiqué lorsque l'itinéraire correspond.
Ok l'a résolu.
Ajout de la solution à GitHub - http://gregorypratt.github.com/AngularDynamicRouting
Dans ma configuration de routage app.js:
$routeProvider.when('/pages/:name', {
templateUrl: '/pages/home.html',
controller: CMSController
});
Puis dans mon contrôleur 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'];
Avec #views étant mon <div id="views" ng-view></div>
Donc maintenant, cela fonctionne avec le routage standard et le routage dynamique.
Pour le tester, j'ai copié about.html, appelé portfolio.html, modifié une partie de son contenu et entré /#/pages/portfolio
dans mon navigateur. Et hop, portfolio.html était affiché ....
Mis à jour Ajout de $ apply et $ compile au code HTML pour que dynamique le contenu peut être injecté.
Je pense que le moyen le plus simple de procéder est de résoudre les itinéraires plus tard. Vous pouvez par exemple les demander via json. Vérifiez que je fabrique une usine à partir de $ routeProvider pendant la phase de configuration, via $ supply, afin de pouvoir continuer à utiliser l'objet $ routeProvider pendant la phase d'exécution et même dans les contrôleurs.
'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();
});
});
Dans les modèles d'URI $ routeProvider, vous pouvez spécifier des paramètres variables, comme ceci: $routeProvider.when('/page/:pageNumber' ...
, et y accéder dans votre contrôleur via $ routeParams.
Il y a un bon exemple à la fin de la page $ route: http://docs.angularjs.org/api/ng.$route
EDIT (pour la question modifiée):
Le système de routage est malheureusement très limité - il y a beaucoup de discussions à ce sujet, et des solutions ont été proposées, notamment via la création de vues nommées multiples, etc. Mais pour le moment, la directive ngView ne sert qu’UNE vue par route, une base individuelle. Vous pouvez vous y prendre de plusieurs manières. La plus simple consiste à utiliser le modèle de la vue comme chargeur, avec une balise <ng-include src="myTemplateUrl"></ng-include>
(la portée $ scope.myTemplateUrl serait créée dans le contrôleur).
J'utilise une solution plus complexe (mais plus propre, pour les problèmes plus importants et plus complexes), en sautant fondamentalement le service $ route, qui est détaillée ici:
Vous ne savez pas pourquoi cela fonctionne mais des itinéraires dynamiques (ou génériques si vous préférez) sont possibles dans 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 -> charge "foo" partiel
example.com/bar-> charge "bar" partiel
Pas besoin d'ajustements dans la vue ng. Le cas '/: a' est la seule variable que j'aie trouvée qui permette d'y arriver .. '/: foo' ne fonctionne pas si vos partiels sont tous foo1, foo2, etc ... '/: a' fonctionne avec tout partiel Nom.
Toutes les valeurs déclenchent le contrôleur dynamique - il n'y a donc pas de "sinon" mais je pense que c'est ce que vous recherchez dans un scénario de routage dynamique ou générique.
Depuis AngularJS 1.1.3, vous pouvez maintenant faire exactement ce que vous voulez en utilisant le nouveau paramètre fourre-tout.
https://github.com/angular/angular.js/commit/7eafbb98c64c0dc079d7d3ec589f1270b7f6fea5
Du commit:
Cela permet à routeProvider d’accepter des paramètres qui correspondent aux sous-chaînes même s’ils contiennent des barres obliques s’ils sont précédés d’un astérisque au lieu de deux-points. Par exemple, des itinéraires tels que
edit/color/:color/largecode/*largecode
correspondent à quelque chose comme cecihttp://appdomain.com/edit/color/brown/largecode/code/with/slashs
.
Je l'ai testé moi-même (avec 1.1.5) et cela fonctionne très bien. N'oubliez pas que chaque nouvelle URL rechargera votre contrôleur. Par conséquent, pour conserver tout type d'état, vous devrez peut-être utiliser un service personnalisé.
Voici une autre solution qui fonctionne 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;
}
})();