3

I am having an Angular issue getting a modal scope to unbind from the parent scope. I want the scope object I pass into the modal to be separate from the corresponding scope object.

No matter how I structure the modal object the parent always mirrors it. The only solution I have found is to change the object property names, but that would be cumbersome to do for every modal in my project.

For example, I can have a $scope variable in the parent $scope.parentData.firstName and a modal variable $scope.modalData.a.b.c.firstName, and the parent will mirror the modal value.

I guess there is some parent child $scope issues here that I am not getting. Here is a plunk illustrating the issue:

http://plnkr.co/edit/5naWXfkv7kmzFp7U2KPv?p=preview

HTML:

<div ng-controller="ModalDemoCtrl">
    <script type="text/ng-template" id="myModalContent.html">
        <div class="modal-header">
            <h3>I'm a modal!</h3>
        </div>
        <div class="modal-body">
                <input ng-model="modalData.a" />
                <input ng-model="modalData.b" />
                <input ng-model="modalData.c" />
            Selected: <b>{{ sourceData }}</b>
        </div>
        <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>
    </script>

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

JS:

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

  $scope.sourceData = {a:'abc',b:'bcd',c:'cde'};

  $scope.open = function () {

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

    modalInstance.result.then(function (selectedItem) {
      $scope.scopeData = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
    });
  };
};

// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.

var ModalInstanceCtrl = function ($scope, $modalInstance, data) {
  $scope.modalData = {};
  $scope.modalData = data;

  $scope.ok = function () {
    $modalInstance.close($scope.modalData);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
};
2
  • just use angular.copy(object). Must remember that objects are passed by reference unless you clone them. This has nothing to do with angular, it is native javascript prototypical inheritance issue. After you modify the copy if you want to merge them back together again use angular.extend() Commented Nov 3, 2014 at 23:56
  • plnkr.co/edit/jAo0c354puN17OX7Ysgl?p=preview Commented Nov 4, 2014 at 0:01

1 Answer 1

6

You are passing a reference to your current object, what you want to do is use angular.copy() to pass a deep copy of the object to the modal plnkr:

var modalInstance = $modal.open({
  templateUrl: 'myModalContent.html',
  controller: ModalInstanceCtrl,
  resolve: {
    data: function () {
      return angular.copy($scope.sourceData); // deep copy
    }
  }
});
Sign up to request clarification or add additional context in comments.

1 Comment

"$scope.ok = function () { $modalInstance.close($scope.modalData); };" Is it the only function that can return data back to parent controller or there are other ways to do so ? Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.