[javascript] AngularJS 동적 라우팅
현재 라우팅이 내장 된 AngularJS 애플리케이션이 있습니다. 작동하고 모든 것이 정상입니다.
내 app.js 파일은 다음과 같습니다.
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: '/' });
}]);
내 앱에는 / pages 디렉토리 내에서 새 html 파일을 복사하고 추가 할 수있는 CMS가 내장되어 있습니다 .
동적으로 추가 된 새 파일에도 여전히 라우팅 공급자를 사용하고 싶습니다.
이상적인 세계에서 라우팅 패턴은 다음과 같습니다.
$ routeProvider.when ( ‘/ pagename ‘, {templateUrl : ‘/ pages / pagename .html’, 컨트롤러 : CMSController});
따라서 새 페이지 이름이 “contact.html”이면 angular가 “/ contact”를 선택하여 “/pages/contact.html”로 리디렉션하고 싶습니다.
이것이 가능할까요?! 그렇다면 어떻게?!
최신 정보
이제 라우팅 구성에 다음이 있습니다.
$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })
내 CMSController에서 :
function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];
그러면 현재 templateUrl이 올바른 값으로 설정됩니다.
그러나 이제 새 templateUrl 값으로 ng-view 를 변경하고 싶습니다 . 이것은 어떻게 이루어 집니까?
답변
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'
});
}
]);
- *를 추가하면 여러 수준의 디렉토리에서 동적으로 작업 할 수 있습니다 . 예 : / page / cars / selling / list 는이 제공 업체에서 포착됩니다.
문서 (1.3.0)에서 :
“templateUrl이 함수 인 경우 다음 매개 변수를 사용하여 호출됩니다.
{Array.}-현재 경로를 적용하여 현재 $ location.path ()에서 추출한 경로 매개 변수 “
또한
when (path, route) : 방법
- 경로는 콜론으로 시작하고 별표로 끝나는 명명 된 그룹을 포함 할 수 있습니다 (예 : 이름 *). 모든 문자는 경로가 일치 할 때 주어진 이름으로 $ routeParams에 열심히 저장됩니다.
답변
좋아, 해결했다.
GitHub에 솔루션 추가-http : //gregorypratt.github.com/AngularDynamicRouting
내 app.js 라우팅 구성에서 :
$routeProvider.when('/pages/:name', {
templateUrl: '/pages/home.html',
controller: CMSController
});
그런 다음 내 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'];
#views가 내 <div id="views" ng-view></div>
이제 표준 라우팅 및 동적 라우팅과 함께 작동합니다.
그것을 테스트하기 위해 나는 그것을 Portfolio.html이라고 부르는 about.html을 복사하고 그것의 내용 중 일부를 변경 /#/pages/portfolio
하고 내 브라우저에 입력 했고 hey presto Portfolio.html이 표시되었습니다 ….
업데이트
$ apply 및 $ compile을 html에 추가하여 동적 콘텐츠를 삽입 할 수 있습니다.
답변
그런 일을하는 가장 쉬운 방법은 나중에 경로를 해결하는 것이라고 생각합니다. 예를 들어 json을 통해 경로를 요청할 수 있습니다. 구성 단계에서 $ provide를 통해 $ routeProvider에서 팩토리를 만들어 실행 단계와 컨트롤러에서도 $ routeProvider 개체를 계속 사용할 수 있는지 확인합니다.
'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();
});
});
답변
$ routeProvider URI 패턴에서 다음과 같이 변수 매개 변수를 지정 $routeProvider.when('/page/:pageNumber' ...
하고 $ routeParams를 통해 컨트롤러에서 액세스 할 수 있습니다.
$ route 페이지 끝에 좋은 예가 있습니다 : http://docs.angularjs.org/api/ng.$route
편집 (편집 된 질문의 경우) :
라우팅 시스템은 안타깝게도 매우 제한적입니다.이 주제에 대해 많은 논의가 있으며, 여러 개의 명명 된 뷰 생성 등을 통해 일부 솔루션이 제안되었습니다. 그러나 현재 ngView 지시문은 경로당 하나의 뷰만 제공합니다. 일대일 기준. 여러 가지 방법으로이 작업을 수행 할 수 있습니다. 더 간단한 방법은 뷰의 템플릿을 <ng-include src="myTemplateUrl"></ng-include>
태그가 있는 로더로 사용하는 것입니다 ($ scope.myTemplateUrl이 컨트롤러에서 생성됨).
나는 기본적으로 $ route 서비스를 완전히 건너 뛰는 더 복잡한 (그러나 더 크고 더 복잡한 문제의 경우 더 깨끗한) 솔루션을 사용합니다.
답변
이것이 왜 작동하는지 확실하지 않지만 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-> “foo”부분로드
example.com/bar-> “bar”부분로드
ng-view에서 조정할 필요가 없습니다. ‘/ : a’케이스는 이것을 달성 할 수있는 유일한 변수입니다. ‘/ : foo’는 부분이 모두 foo1, foo2 등이 아니면 작동하지 않습니다. ‘/ : a’는 모든 부분과 함께 작동합니다. 이름.
모든 값은 동적 컨트롤러를 실행하므로 “otherwise”는 없지만 동적 또는 와일드 카드 라우팅 시나리오에서 찾고있는 것이라 생각합니다.
답변
AngularJS 1.1.3부터는 새로운 catch-all 매개 변수를 사용하여 원하는 작업을 정확하게 수행 할 수 있습니다.
https://github.com/angular/angular.js/commit/7eafbb98c64c0dc079d7d3ec589f1270b7f6fea5
커밋에서 :
따라서 routeProvider는 콜론 대신 별표가 접두사로 붙은 경우 슬래시가 포함 된 경우에도 하위 문자열과 일치하는 매개 변수를 허용 할 수 있습니다. 예를 들어, 같은 경로는 이와 같은 것과
edit/color/:color/largecode/*largecode
일치합니다
http://appdomain.com/edit/color/brown/largecode/code/with/slashs
.
나는 (1.1.5 사용) 직접 테스트했으며 훌륭하게 작동합니다. 각 새 URL은 컨트롤러를 다시로드하므로 모든 종류의 상태를 유지하려면 사용자 지정 서비스를 사용해야 할 수 있습니다.
답변
다음은 잘 작동하는 또 다른 솔루션입니다.
(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;
}
})();