Animal2
Animal2

Reputation: 75

Scope issues when declaring controller for a modal in AngularUI/Boostrap

What I'm trying to do is have a custom directive inside a modal that just returns a list of files. The issue I'm having is that the scope seems to be different depending on how I declare my controller on my modal. Inside my modal I have a custom directive with an isolated scope that just returns a list of selected files. The first method I have is declaring it as a parameter in the modal creation.

$scope.openModal = function(){
  uploadDialog = $modal.open({
  templateUrl: 'modal.html',
  size: 'lg',
  controller:'modalController'
});

The second method I tried is declaring it at the top of the div of the modal template so I had to make a new div and wrap the whole modal template.

The second method returns everything fine, but the first method doesn't return it at all. I did notice while debugging that the "this" property has the value selectedFiles. Why does the two method yield different results?

Method 1 Plunker: http://plnkr.co/edit/6FTQq7fT49lETR5TEzaF?p=preview

Method 2 Plunker: http://plnkr.co/edit/QWnbH8GZArMgYqgcQ8L9?p=preview

Upvotes: 1

Views: 524

Answers (1)

runTarm
runTarm

Reputation: 11547

To answer your question, please first see my comments in the DOM elements after a modal template has been compiled below:

Method 1:

<!-- Method 1 controller's scope is here, it is the same as modal's scope -->
<div class="modal fade in ng-isolate-scope">
  <div class="modal-dialog modal-lg">

    <!-- This ng-transclude create a new scope for each its children elements -->
    <div class="modal-content" ng-transclude>
      <div class="modal-header ng-scope">
        <h3 class="modal-title">Test</h3>
      </div>

      <!-- The selectedFiles will be stored in this scope, not the controller scope above. -->
      <div class="modal-body ng-scope">
        <upload-dir files="selectedFiles" class="ng-isolate-scope">
        <div>{{selectedFiles}}</div>
        <button ng-click="clickHere(selectedFiles)">click here</button>
        <div>From $scope: <input type="text" ng-model="test"></div>
        <div>From parameter: <input type="text" ng-model="testParam"></div>
      </div>
      <div class="modal-footer ng-scope"></div>
    </div>
  </div>
</div>

Method 2:

<!-- The modal's scope is here -->
<div class="modal fade in ng-isolate-scope">
  <div class="modal-dialog modal-lg">

    <!-- This ng-transclude create a new scope for each its children elements -->
    <div class="modal-content" ng-transclude>

      <!-- Method 2 controller's scope is here -->
      <div ng-controller="modalController" class="ng-scope">
        <div class="modal-header">
          <h3 class="modal-title">Test</h3>
        </div>

        <!-- There is no new scope created here, -->
        <!-- so the selectedFiles will be stored in the controller's scope above -->
        <div class="modal-body">
          <upload-dir files="selectedFiles" class="ng-isolate-scope">
          <div>{{selectedFiles}}</div>
          <button ng-click="clickHere(selectedFiles)">click here</button>
          <div>From $scope: <input type="text" ng-model="test"></div>
          <div>From parameter: <input type="text" ng-model="testParam"></div>
        </div>
        <div class="modal-footer"></div>
      </div>
    </div>
  </div>
</div>

As you can see, the controller's scope in Method 1 is not the nearst scope that the selectedFiles is defined, that why the $scope.selectedFiles and $scope.test are undefined.

You could workaround the issue by keeping the selectedFiles in some object before put it in scope, e.g. $scope.model.selectedFiles. Please see the plunker below for an example.

Method 1 Plunker (Modified): http://plnkr.co/edit/pP2L1ZJLxXJXgqR3QAIT?p=preview

Hope this clear things up!

Upvotes: 2

Related Questions