Integrating directive in Angular UI Modal

2019-08-11 13:51发布

问题:

In this plunk I have the following:

  • A control object shared between the controller and the directive.
  • The directive declares a method in the control object.
  • The controller invokes the method to set a value.
  • The directive is included in an Angular UI Modal.

For some reason the control object is empty when the modal is opened (look at the console log). How to invoke the method from the controller to set the field value?

HTML

<div ng-app="app" ng-controller="myCtl">

        <button ng-click="openModal()">Open modal</button>

        <script type="text/ng-template" id="myModalContent.html">

            <div class="modal-header">
                <h4 class="modal-title">The Title</h4>
            </div>

            <ddl control="ddlControl"></ddl>                

            <div class="modal-footer">
                <button type="submit">Submit</button>
            </div>

       </script>

    </div>

Javascript

var app = angular.module('app', ['ui.bootstrap']);
app.controller('myCtl', function($scope,$uibModal) {

        $scope.ddlControl = {};

        $scope.openModal = function() {
          $scope.modalInstance = $uibModal.open({
              templateUrl: 'myModalContent.html',
              scope: $scope
            }); 

          console.log($scope.ddlControl);
          $scope.ddlControl.set();

        };
})

.directive('ddl', function () {

    var directive = {};
    directive.restrict = 'EA';
    directive.scope = {
         control: '='
    };
    directive.template = '<div>someValue: {{someValue}}</div>';
    directive.link = function (scope, element, attrs) {

        scope.control = scope.control || {};

        scope.control.set = function() {
           scope.someValue = 1;
        };

    };
    return directive;
});

回答1:

There is a race condition between opening the modal and running a digest of the modal HTML.

When the button is clicked $scope.openModal() is executed. The modal opens and gets into the digest phase. But javascript is not waiting until the digesting has been completed, so it continues executing $scope.openModal() until the end.

You need to handle the promise of $uibModal.open().rendered(). The uibModal resolves the rendered promise when it's done.

    $scope.openModal = function() {
      $scope.modalInstance = $uibModal.open({
          templateUrl: 'myModalContent.html',
          scope: $scope
        }).rendered.then(function() {
             console.log($scope.ddlControl);
             $scope.ddlControl.set(); 
        }); 
    };

The $uibModal.open() function returns the following:

Object {result: Promise, opened: Promise, rendered: Promise}

In the promise block of rendered, you can safely make use of the fields that has been changed by the directive.

Plunker: http://plnkr.co/edit/GnIThstxkuR06felh8Pe?p=preview