web-dev-qa-db-fra.com

AngularJS: plusieurs vues avec routage sans perte de portée

J'essaie d'implémenter une interface classique de liste/détails. Lorsque je clique sur un élément de la liste, je souhaite afficher un formulaire de modification pour cet élément tout en affichant la liste . J'essaie de contourner la limitation de 1 vue par page d'Angular et j'ai décidé de le faire en faisant en sorte que toutes les URL soient routées vers le même contrôleur/vue. (Peut-être que c'est la racine de mon problème et je suis ouvert aux alternatives.)

Routage:

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

La vue (/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>

Manette:

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);
}

Problèmes:

  1. Lorsque vous cliquez sur un lien de modification, le contrôleur est ré-instancié avec une nouvelle portée. Je dois donc ré-initialiser la liste des utilisateurs. (Dans un exemple plus complexe, l'entrée de l'utilisateur stockée serait liée au modèle et elle serait également perdue.) Je préférerais conserver l'étendue de la route précédente.
  2. Je préférerais utiliser un contrôleur distinct (ou, comme beaucoup d’autres Angular développeurs se sont plaints, la possibilité d’avoir plusieurs vues affichées!), Mais cela entraîne le même problème de perte de portée.
12
Keith

Essayez d’utiliser ui-router: http://github.com/angular-ui/ui-router .

Ils ont des vues imbriquées et une gestion d’état plus facile que le routage angulaire par défaut :-)

14
Andrew Joslin

Les vues multiples ne sont pas prises en charge dans AngularJS. Vous pouvez utiliser cette bibliothèque à cette fin, qui prend en charge toute quantité de vues imbriquées sur la page, où chaque niveau est configuré indépendamment avec son propre contrôleur et son propre modèle:

http://angular-route-segment.com

Il est beaucoup plus simple à utiliser que ui-router. Exemple de configuration peut ressembler à ceci:

$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

J'ai trouvé Angular Multi View être une aubaine pour ce scénario. Il vous permet de conserver la portée lorsque la route change et permet à plusieurs contrôleurs de partager la même route sans imbriquer vos vues .

Je recommande Angular Multi-vues si vous avez plus de 2 vues sur votre page. Sinon, lorsque vous utilisez ui-router, l'imbrication de plusieurs vues devient très compliquée.

1
Keith

Je suis venu avec le même problème et je n'aime pas personnellement les plugins quand ils ne sont pas absolument inévitables. Je viens de déplacer singleton part à un service.

Dans mon cas, il y a: id [/: mode] routes et je veux réagir différemment si l’utilisateur change juste de mode ou d’id. Ainsi, je dois connaître l'identifiant précédent.

Il existe donc un service avec la méthode activate qui met à jour son état. Et la portée est réinitialisée à chaque fois avec le code suivant.

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;
}]);

Dans la méthode activate, je peux comparer id à activeItem.id du singleton et réagir différemment.

0
dareka