AngularJS 동적 라우팅


88

현재 라우팅이 내장 된 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 를 변경하고 싶습니다 . 이것은 어떻게 이루어 집니까?

답변:


132
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에 열심히 저장됩니다.

5
시대에 따라 움직여야합니다 ... v1.0.2에서 누락되었던 기능을 이제 사용할 수 있습니다. 이에 대한 수락 된 답변 업데이트
Greg

솔직히 내가 현재 1.3 베타 버전이 작업도 없었어 될하려면
아르키메데스 Trajano

실제로 내가이 작업을 수행했을 때 작동하게되었습니다 ... when ( '/ : page', {templateUrl : function (parameters) {return parameters.page + '.html';}
Archimedes Trajano

진심으로 .. 수동 라우팅 말도 그건 ... 각도는 기본 동작으로하지 않는 것을 정말 바보
Guilherme 페레이라

3
설명해주십시오. 어디에서 urlattr설정되거나 전송 urlattr.name됩니다. 무엇 을 생산할 것인가?
Sami

37

좋아, 해결했다.

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에 추가하여 동적 콘텐츠를 삽입 할 수 있습니다.


2
이것은 내가 올바르게 이해하는 경우 정적 콘텐츠에서만 작동합니다. 이는 컨트롤러를 인스턴스화 한 후 jQuery (angular 범위 외부)를 통해 DOM을 변경하기 때문입니다. {{this}}와 같은 변수는 작동 할 수 있지만 (사용해보아야합니다) 지시문은 작동하지 않을 가능성이 높습니다. .. 지금 유용 할 수있다,이주의하십시오, 나중에 코드를 깰 수
티아구 Roldão

사실, 바인딩은 작동하지 않지만 클라이언트가 새 페이지를 추가 할 수만 있기를 원하기 때문에 너무 소란스럽지 않습니다. 내가 추가하는 모든 페이지는 경로 구성을 통해 적절하게 지정합니다. 그래도 좋은 지적입니다.
Greg

1
정적 html 콘텐츠를 렌더링하려는 경우 나쁜 해결책은 아닙니다. 당신이 명심하는 한 당신은 본질적으로 정적 (각이 아닌) 콘텐츠로 ng-view를 재정의하고 있습니다. 이를 염두에두고 둘을 분리하여 <div id = "user-views"> </ div> 요소와 같은 것을 만들고 거기에 "사용자 템플릿"을 삽입하는 것이 더 깔끔 할 것입니다. 또한 $ route.current.templateUrl을 재정의하는 것은 전혀 의미가 없습니다. $ scope.userTemplate 모델을 만들고 $ ( '# user-views "). load ($ scope.userTemplate)를 수행하는 것이 더 깔끔하고 각도를 깨뜨리지 않습니다. 코드입니다.
티아구 Roldão

1
아니요-ng-view 지시문은 다소 제한적입니다. 또는 더 잘 말하면 네이티브 라우팅 시스템 (이는 여전히 제한적 임)과 함께 사용하기위한 것입니다. 말한대로 DOM 요소에 콘텐츠를 주입 한 다음 $ compile 메서드를 호출하여 angular에 구조를 다시 읽도록 지시 할 수 있습니다. 그러면 수행해야하는 바인딩이 트리거됩니다.
Tiago Roldão 2012

2
작동하지만 컨트롤러에서 DOM 조작을해서는 안됩니다.
dmackerman

16

그런 일을하는 가장 쉬운 방법은 나중에 경로를 해결하는 것이라고 생각합니다. 예를 들어 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로 사용할 별칭 은 보안 및 앱 응집력과 잘 어울리지 않습니다. 어느 쪽이든 멋진 기술 (공감!) factoryconfig
Cody

@Cody 보안 / 앱 통합 메모에 대해 설명해 주시겠습니까? 우리는 비슷한 보트에 있으며 위의 답변과 같은 것이 정말 편리합니다.
virtualandy 2014

2
@virtualandy, 일반적으로 제공 업체를 여러 단계에서 사용할 수 있도록 만드는 것은 좋은 접근 방식이 아닙니다. 이는 구성 단계에서 숨겨야하는 높은 수준의 유틸리티를 유출 할 수 있습니다. 내 제안은 UI-Router (많은 어려움을 처리)를 사용하고 "resolve", "controllerAs"및 templateUrl을 함수로 설정하는 것과 같은 기타 기능을 사용하는 것입니다. 또한 라우트 체계 (템플릿, 템플릿 Url, 컨트롤러 등)의 모든 부분을 $ 보간 할 수있는 공유 할 수있는 "presolve"모듈을 구축했습니다. 위의 솔루션은 더 우아한 솔루션이지만 주요 관심사는 무엇입니까?
Cody 2014

1
@virtualandy, 여기에 lazyLoaded 템플릿, 컨트롤러 등을위한 모듈이 있습니다. 사과는 저장소에 있지 않지만 여기에 바이올린이 있습니다 : jsfiddle.net/cCarlson/zdm6gpnb ... URL 매개 변수를 기반으로합니다. 모듈은 약간의 작업을 사용할 수 있지만 최소한 시작점은 있습니다.
Cody 2014

@Cody-문제 없습니다. 샘플 및 추가 설명에 감사드립니다. 말이 되네요. 우리의 경우 angular-route-segment를 사용 하고 있으며 잘 작동합니다. 그러나 이제 "동적"경로를 지원해야합니다 (일부 배포에는 페이지의 전체 기능 / 경로가 없거나 이름 등이 변경 될 수 있음). 실제로 구현하기 전에 경로를 정의하는 일부 JSON에서로드하는 개념이 우리의 생각이었습니다. 그러나 분명히 .config () 내에서 $ http / $ providers를 사용하는 데 문제가 발생했습니다.
virtualandy 2014

7

$ 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 서비스를 완전히 건너 뛰는 더 복잡한 (그러나 더 크고 더 복잡한 문제의 경우 더 깨끗한) 솔루션을 사용합니다.

http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm


나는 ng-include방법을 좋아한다 . 정말 간단하고 DOM을 조작하는 것보다 훨씬 더 나은 접근 방식입니다.
Neel 2014 년

5

이것이 왜 작동하는지 확실하지 않지만 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"는 없지만 동적 또는 와일드 카드 라우팅 시나리오에서 찾고있는 것이라 생각합니다.


2

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은 컨트롤러를 다시로드하므로 모든 종류의 상태를 유지하려면 사용자 지정 서비스를 사용해야 할 수 있습니다.


0

다음은 잘 작동하는 또 다른 솔루션입니다.

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

    }

})();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.