web-dev-qa-db-ja.com

AngularJS:スコープを失うことなくルーティングする複数のビュー

クラシックなリスト/詳細UIを実装しようとしています。リスト内のアイテムをクリックすると、そのアイテムの編集フォームを表示したいリストを表示したまま。 Angularの1ページあたり1ビューの制限を回避しようとしていますが、すべてのURLを同じコントローラー/ビューにルーティングすることで回避することにしました。 (おそらくこれが私の問題の根源であり、私は代替案を受け入れています。)

ルーティング:

$routeProvider
    .when('/list', { templateUrl: '/Partials/Users.html', controller: UserController })
    .when('/edit/:UserId', { templateUrl: '/Partials/Users.html', controller: UserController })
    .otherwise({ redirectTo: '/list' });

ビュー(/Partials/Users.html):

<!-- List of users -->
<div ng-repeat="user in Users">
    <a href="*/edit/{{ user.Id }}">Edit {{ user.Name }}</a>
</div>

<!-- Edit form -->
<div>
    {{ SelectedUser.Name }}
</div>

コントローラ:

function UserController($scope, $routeParams) {
    // the model for the list
    $scope.Users = GetUserListFromService();

    // the model for the edit form
    if ($routeParams.UserId != null)
        $scope.SelectedUser = GetUserFromService($routeParams.UserId);
}

問題:

  1. 編集リンクをクリックすると、コントローラーが新しいスコープで再インスタンス化されるため、ユーザーリストを再初期化する必要があります。 (より複雑な例では、モデルにバインドされて保存されたユーザーからの入力があり、これも失われます。)以前のルートのスコープを保持したいと思います。
  2. 別のコントローラーを使用したいのですが(または、他の多くのAngular開発者が不満を言っているように、複数のビューを表示する機能!))、スコープが失われるという同じ問題が発生します。
12
Keith

Ui-routerを使用してみてください: http://github.com/angular-ui/ui-router

それらはネストされたビューを持ち、angularデフォルトのルーティング:-)よりも簡単な状態管理を持っています

14
Andrew Joslin

コアAngularJSでは複数のビューはサポートされていません。このライブラリは、ページ上の任意の数のネストされたビューをサポートするこの目的に使用できます。各レベルは、独自のコントローラーとテンプレートを使用して個別に構成されます。

http://angular-route-segment.com

Ui-routerよりもはるかに簡単に使用できます。サンプル構成は次のようになります。

$routeSegmentProvider.

when('/section1',          's1.home').
when('/section1/prefs',    's1.prefs').
when('/section1/:id',      's1.itemInfo.overview').
when('/section1/:id/edit', 's1.itemInfo.edit').
when('/section2',          's2').

segment('s1', {
    templateUrl: 'templates/section1.html',
    controller: MainCtrl}).

within().

    segment('home', {
        templateUrl: 'templates/section1/home.html'}).

    segment('itemInfo', {
        templateUrl: 'templates/section1/item.html',
        controller: Section1ItemCtrl,
        dependencies: ['id']}).

    within().

        segment('overview', {
            templateUrl: 'templates/section1/item/overview.html'}).

        segment('edit', {
             templateUrl: 'templates/section1/item/edit.html'}).

        up().

    segment('prefs', {
        templateUrl: 'templates/section1/prefs.html'}).

    up().

segment('s2', {
    templateUrl: 'templates/section2.html',
    controller: MainCtrl});
7
artch

Angular Multi View がこのシナリオの天の恵みであることがわかりました。ルートの変更時にスコープを保持し、ビューをネストせずに複数のコントローラーが同じルートを共有できるようにします

ページに3つ以上のビューがある場合は、Angular Multi Viewをお勧めします。そうでない場合、ui-routerを使用すると、複数のビューをネストするのが非常に速くなります。

1
Keith

私は同じ問題を思いついたのですが、絶対に避けられないわけではないのに、個人的にプラグインは好きではありません。シングルトンパーツをサービスに移動しました。

私の場合、:id [/:mode]ルートがあり、ユーザーがモードまたはIDだけを変更した場合も、別の方法で対応したいと思います。したがって、私は以前のIDを知る必要があります。

そのため、状態を更新するactivateメソッドを備えたサービスがあります。そして、スコープは次のコードで毎回再初期化されます。

module.controller('MyController', ['$scope', '$routeParams', 'navigator', function($scope, $routeParams, navigator) {
    var id = null;
    var mode = null;

    if (typeof($routeParams.id)!='undefined')
    {
        id = $routeParams.id;
    }

    if (typeof($routeParams.mode)!='undefined')
    {
        mode = $routeParams.mode;
    }

    navigator.activate(id, mode);

    $scope.items = navigator.items;
    $scope.activeItem = navigator.activeItem;
    $scope.modes = navigator.modes;
    $scope.activeMode = navigator.activeMode;
}]);

Activateメソッドでは、idをシングルトンのactiveItem.idと比較して、異なる反応をすることができます。

0
dareka