web-dev-qa-db-fra.com

Problème de portée dans AngularJS avec l’interface utilisateur angulaire Bootstrap Modal

plunker: http://plnkr.co/edit/wURNg8ByPYbEuQSL4xwg

example.js:

angular.module('plunker', ['ui.bootstrap']);
  var ModalDemoCtrl = function ($scope, $modal) {

  $scope.open = function () {
    var modalInstance = $modal.open({
      templateUrl: 'modal.html',
      controller: 'ModalInstanceCtrl'
    });
  };
};

var ModalInstanceCtrl = function ($scope, $modalInstance) {

  $scope.ok = function () {
    alert($scope.text);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
};

index.html:

<!doctype html>
<html ng-app="plunker">
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
    <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.6.0.js"></script>
    <script src="example.js"></script>
    <link href="//netdna.bootstrapcdn.com/Twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
  </head>
  <body>

  <div ng-controller="ModalDemoCtrl">
    <button class="btn" ng-click="open()">Open me!</button>
    <div ng-show="selected">Selection from a modal: {{ selected }}</div>
  </div>
 </body>
</html>

modal.html:

<div class="modal-header">
    <h3>I'm a modal!</h3>
</div>
<textarea ng-model="text"></textarea>
<div class="modal-footer">
    <button class="btn btn-primary" ng-click="ok()">OK</button>
    <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>

Pourquoi je ne peux pas obtenir le $ scope.text défini dans ModalInstanceCtrl, même si je peux utiliser $ scope.ok et $ scope.cancel?

52
Manuel Bitto

On dirait un problème de portée. Je l'ai fait fonctionner comme ceci:

var ModalInstanceCtrl = function ($scope, $modalInstance) {
    $scope.input = {};
    $scope.ok = function () {
        alert($scope.input.abc);
    };

    $scope.cancel = function () {
        $modalInstance.dismiss('cancel');
    };
};

HTML:

<textarea ng-model="input.abc"></textarea>
72
AlwaysALearner

pdate Nov 2014: le problème est corrigé avec angular-ui-bootstrap .12. - la portée de la transclusion est fusionnée avec la portée du contrôleur. Il n'y a pas besoin de faire quoi que ce soit. Il suffit de rester avec:

<textarea ng-model="text"></textarea>

Avant le 0.12.0:

Les modaux de l'interface utilisateur angulaire utilisent la transclusion pour attacher un contenu modal, ce qui signifie que toutes les nouvelles entrées de portée effectuées dans modal sont créées dans une portée enfant.

Vous devez utiliser l’héritage et initialiser l’entrée vide text dans le parent $scope ou vous pouvez attacher explicitement l’entrée à la portée parent:

<textarea ng-model="$parent.text"></textarea>
16
gertas

Essayons d'expliquer la raison. code source modal ui-bootstrap:

.directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
return {
  restrict: 'EA',
  scope: {
    index: '@',
    animate: '='
  },
  replace: true,
  transclude: true,
  templateUrl: function(tElement, tAttrs) {
    return tAttrs.templateUrl || 'template/modal/window.html';
  },

et le code source du template - window.html:

<div tabindex="-1" role="dialog" class="modal fade" ng-class="{in: animate}" ng-style="{'z-index': 1050 + index*10, display: 'block'}" ng-click="close($event)">
<div class="modal-dialog" ng-class="{'modal-sm': size == 'sm', 'modal-lg': size == 'lg'}"><div class="modal-content" modal-transclude></div></div>

il y a une directive modal-transclude , le contenu de votre dialogue va y être inséré, c'est son code source:

.directive('modalTransclude', function () {
return {
  link: function($scope, $element, $attrs, controller, $transclude) {
    $transclude($scope.$parent, function(clone) {
      $element.empty();
      $element.append(clone);
    });
  }
};

})

jetons maintenant un coup d'oeil à la documentation officielle de $ compile:

Transclusion Functions

When a directive requests transclusion, the compiler extracts its contents and provides 
a transclusion function to the directive's link function and controller. 
This transclusion function is a special linking function that will return the compiled 
contents linked to a **new transclusion scope.**

transclude créera une nouvelle portée de la portée du contrôleur

3
笑笑十年