web-dev-qa-db-fra.com

Problèmes de périmètre avec Angular UI modal

Je ne parviens pas à comprendre/utiliser les oscilloscopes pour un modal angular UI).

Bien que cela ne soit pas immédiatement apparent ici, les modules et tout sont correctement configurés (pour autant que je sache), mais ces exemples de code en particulier sont ceux où je trouve le bogue.

index.html (la partie importante)

<div class="btn-group">
    <button class="btn dropdown-toggle btn-mini" data-toggle="dropdown">
        Actions
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu pull-right text-left">
        <li><a ng-click="addSimpleGroup()">Add Simple</a></li>
        <li><a ng-click="open()">Add Custom</a></li>
        <li class="divider"></li>
        <li><a ng-click="doBulkDelete()">Remove Selected</a></li>
    </ul>
</div>

Controller.js (encore une fois, la partie importante)

MyApp.controller('AppListCtrl', function($scope, $modal){
    $scope.name = 'New Name';
    $scope.groupType = 'New Type';

    $scope.open = function(){
        var modalInstance = $modal.open({
            templateUrl: 'partials/create.html',
            controller: 'AppCreateCtrl'
        });
        modalInstance.result.then(function(response){

            // outputs an object {name: 'Custom Name', groupType: 'Custom Type'}
            // despite the user entering customized values
            console.log('response', response);

            // outputs "New Name", which is fine, makes sense to me.                
            console.log('name', $scope.name);

        });
    };
});

MyApp.controller('AppCreateCtrl', function($scope, $modalInstance){
    $scope.name = 'Custom Name';
    $scope.groupType = 'Custom Type';

    $scope.ok = function(){

        // outputs 'Custom Name' despite user entering "TEST 1"
        console.log('create name', $scope.name);

        // outputs 'Custom Type' despite user entering "TEST 2"
        console.log('create type', $scope.groupType);

        // outputs the $scope for AppCreateCtrl but name and groupType
        // still show as "Custom Name" and "Custom Type"
        // $scope.$id is "007"
        console.log('scope', $scope);

        // outputs what looks like the scope, but in this object the
        // values for name and groupType are "TEST 1" and "TEST 2" as expected.
        // this.$id is set to "009" so this != $scope
        console.log('this', this);

        // based on what modalInstance.result.then() is saying,
        // the values that are in this object are the original $scope ones
        // not the ones the user has just entered in the UI. no data binding?
        $modalInstance.close({
            name: $scope.name,
            groupType: $scope.groupType
        });
    };
});

create.html (dans son intégralité)

<div class="modal-header">
    <button type="button" class="close" ng-click="cancel()">x</button>
    <h3 id="myModalLabel">Add Template Group</h3>
</div>
<div class="modal-body">
    <form>
        <fieldset>
            <label for="name">Group Name:</label>
            <input type="text" name="name" ng-model="name" />           
            <label for="groupType">Group Type:</label>
            <input type="text" name="groupType" ng-model="groupType" />
        </fieldset>
    </form>
</div>
<div class="modal-footer">
    <button class="btn" ng-click="cancel()">Cancel</button>
    <button class="btn btn-primary" ng-click="ok()">Add</button>
</div>

Ma question est donc la suivante: pourquoi la portée n’est-elle pas liée à l’interface utilisateur? et pourquoi this a-t-il les valeurs personnalisées, mais $scope ne fait pas?

J'ai essayé d'ajouter ng-controller="AppCreateCtrl" au corps div dans create.html, mais cela a généré une erreur: "Fournisseur inconnu: $ modalInstanceProvider <- $ modalInstance", donc aucune chance.

À ce stade, ma seule option est de renvoyer un objet avec this.name et this.groupType à la place d'utiliser $scope, mais ça ne va pas.

80
coblr

J'ai le mien pour travailler comme ça:

var modalInstance = $modal.open({
  templateUrl: 'partials/create.html',
  controller: 'AppCreateCtrl',
  scope: $scope // <-- I added this
});

Pas de nom de formulaire, pas de $parent. J'utilise AngularUI Bootstrap version 0.12.1.

J'ai été prévenu de cette solution par this .

59
Jason Swett

Lorsque des portées imbriquées sont impliquées, ne liez pas <input> Directement aux membres de la portée:

<input ng-model="name" /> <!-- NO -->

Liez-les à au moins un niveau plus profond:

<input ng-model="form.name" /> <!-- YES -->

La raison en est que les portées héritent de manière prototypique de leur portée parent. Ainsi, lors de la définition des membres de 1er niveau, ceux-ci sont définis directement sur la portée de l'enfant, sans affecter le parent. Contrairement à cela, lors de la liaison à des champs imbriqués (form.name), Le membre form est lu à partir de la portée parent. Par conséquent, l'accès à la propriété name permet d'accéder à la bonne cible.

Lire une description plus détaillée ici .

66

Mise à jour nov. 2014:

En fait, votre code devrait fonctionner après la mise à niveau vers ui-bootstrap 0.12.0. La portée transcluse est fusionnée avec la portée du contrôleur. Plus besoin de $parent ou form. des trucs.

avant le 0.12.:

Le modal utilise la transclusion pour insérer son contenu. Grâce à ngForm, vous pouvez contrôler la portée par l'attribut name. Donc, pour échapper à la portée transcluse, modifiez simplement la forme de cette façon:

<form name="$parent">

ou

<form name="$parent.myFormData">

Les données du modèle seront disponibles dans la portée du contrôleur.

7
gertas

J'ajoute scope: $ scope alors ça marche .Cool

1
JBRandri
$scope.open = function () {

          var modalInstance = $uibModal.open({
              animation: $scope.animationsEnabled,
              templateUrl: 'myModalContent.html',
              controller: 'salespersonReportController',
              //size: size
              scope: $scope
            });

      };

ça marche pour moi portée: $ portée merci Jason Swett

1
ali Shoaib