web-dev-qa-db-ja.com

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'、controller: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が正しい値に設定されます。

ただし、新しいng-viewを変更したいtemplateUrl値。これはどのように達成されますか?

88
Greg
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):メソッド

  • pathには、コロンで始まりスターで終わる名前付きグループを含めることができます(例:name *)。ルートが一致すると、すべてのキャラクターは指定された名前で$ routeParamsに熱心に保存されます。
131
Robin Rizvi

わかった。

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を入力すると、presto Portfolio.htmlが表示されました。

Updatedhtmlに$ applyと$ compileを追加して、動的にコンテンツを注入できます。

37
Greg

そのようなことをする最も簡単な方法は、後でルートを解決することだと思います。たとえば、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();
    });
});
16
eazel7

$ routeProvider URIパターンでは、次のように変数パラメーターを指定できます:$routeProvider.when('/page/:pageNumber' ...、コントローラーで$ routeParamsを介してアクセスします。

$ routeページの最後に良い例があります: http://docs.angularjs.org/api/ng.$ro​​ute

EDIT(編集された質問用):

ルーティングシステムは残念ながら非常に限られています。このトピックについては多くの議論があり、複数の名前付きビューの作成など、いくつかのソリューションが提案されています。しかし、現在、ngViewディレクティブは1対1ベース。これについては複数の方法で実行できます。より簡単な方法は、ビューのテンプレートをローダーとして使用し、その中に<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

7
Tiago Roldão

なぜこれが機能するのかはわかりませんが、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->「バー」部分ロード

Ngビューで調整する必要はありません。 '/:a'ケースは、これを実現する唯一の変数です。 '/:foo'は、パーシャルがすべてfoo1、foo2などでない限り機能しません。名。

すべての値が動的コントローラーを起動します。したがって、「そうでなければ」はありませんが、動的またはワイルドカードルーティングシナリオで探しているものだと思います。

5
Matthew Luchak

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ごとにコントローラーがリロードされるため、あらゆる種類の状態を維持するには、カスタムサービスを使用する必要がある場合があることに注意してください。

2
Dave

うまく機能する別のソリューションを次に示します。

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

    }

})();
0
kevinius