Justin
Justin

Reputation: 568

Collection-Repeat and $ionicModal Strange Behavior

I am making a directory app that comprises roughly 200 list items (employees). The app worked as intended using ng-repeat, however, it was sluggish to load. I switched to Collection-Repeat to take advantage of the speed boost but I am getting bizarre behaviors that I can't figure out.

The list items are rendering correctly, alphabetically with the category titles added successfully. The problem is, each list item has a ng-click attribute that opens an $ionicModal. The modal for each item opens, but the loaded data is incorrect.

When the modal opens, it starts at the bottom of the page - I can see the contents for half a second before it animates to the middle of the screen. To start, the loaded data is correct. As it animates, it switches to another employees data. I can't seem to figure out why. I'm new to angular/ionic so any pointers would be great. Thanks!

EDIT - Out of curiousity, I added a second ng-controller="ModalCtrl" ng-click="openModal();" to each element as a button. Clicking on the element does the usual - opens the modal with the wrong employee. Clicking on the newly created button however creates TWO modals (stacked on eachother) BOTH with the correct employee. Removing either instance to the ng-controller or ng-click puts me back at square one with only one modal of incorrect data. Why is this? Why does adding a second ng-click correct the problem (despite having two modals)?

EDIT - Here is a link to a codepen sample (dumbed down, but proves my issue: http://codepen.io/anon/pen/zijFv?editors=101

My HTML looks like this:

<div class="list">
   <a class="item my-item"            
      collection-repeat="row in contacts"
      collection-item-height="getItemHeight(row)"
      collection-item-width="'100%'"
      ng-class="{'item-divider': row.isLetter}">

      <!-- ADDED BUTTON SEE EDIT COMMENT ABOVE -->
      <button ng-if="!row.isLetter" ng-controller="ModalCtrl" ng-click="openModal();">Click</button>

      <img ng-controller="ModalCtrl" ng-click="modal.show()" ng-if="!row.isLetter" ng-src="data:image/jpeg;base64,{{row.image}}">
      <h2>{{row.title || (row.firstname+' '+row.lastname)}}</h2>
      <p ng-if="!row.isLetter"><em>{{row.jobtitle}}</em></p>                   
   </a>
</div>

My Modal HTML is this:

<header class="bar bar-header bar-lsi">
  <h1 class="title">Contact Information</h1>
  <div class="button button-clear" ng-click="closeModal()">
    <span class="icon ion-close"></span>
  </div>
</header>

<ion-content has-header="true" style="margin-top: 0px !important;">        

  <div class="list card" style="border-radius: 0px !important;">

     <div class="item item-avatar item-text-wrap">
       <img ng-src="data:image/jpeg;base64,{{row.image}}">
       <h2>{{row.firstname}} {{row.lastname}}</h2>
       <p>{{row.jobtitle}}</p>
     </div>

     <a href="tel:{{row.phone}}" class="item item-icon-left">
       <i class="icon ion-iphone"></i>
       {{row.phone}}
     </a>

     <a href="mailto:{{row.email}}" class="item item-icon-left">
      <i class="icon ion-email"></i>
      {{row.email}}
     </a>         

   </div>

</ion-content>

And then I have my basic controller:

.controller('ModalCtrl', function($scope, $ionicModal) {

    $ionicModal.fromTemplateUrl('my-modal.html', { 
        scope: $scope, 
        animation: 'slide-in-up'
    }).then(function(modal) {
        $scope.modal = modal;
    });
    $scope.openModal = function() {
        $scope.modal.show();
    };
    $scope.closeModal = function() {
        $scope.modal.hide();
    };

    $scope.$on('$destroy', function() {
        $scope.modal.remove();
    });

})

Upvotes: 1

Views: 1733

Answers (1)

Watto
Watto

Reputation: 81

I think the problem is that you aren't passing to the modal template any value. It's getting residual values. I see too that you are using too much ng-controller and ng-click in items list and what is inside it. I mean, if you use ng-click for A.item, you don't need to use ng-click for the image inside it.

Let's see some code:

<a class="item my-item"
   collection-repeat="row in contacts"
   collection-item-height="getItemHeight(row)"
   collection-item-width="'100%'"
   ng-class="{'item-divider': row.isLetter}"
   ng-controller="ModalCtrl" ng-click="openModal(row);">

       <img ng-if="!row.isLetter" ng-src="http://placehold.it/65x65">
       <h2>{{row.title || (row.firstname+' '+row.lastname)}}</h2>
       <p ng-if="!row.isLetter"><em>{{row.jobtitle}}</em></p>
</a>

As you can see, I've removed all ng-click and ng-controller inside A tag, and I've left only what is attributes of A tag. You can notice too that I pass the object row to the openmModal() function.

In controller, I've made next changes:

$scope.openModal = function(item) {
   $scope.modal.row = item;
   $scope.modal.show();
};

And in the modal template I've used modal.row as variable with the data from the item list touched. So in template I use it like this:

<div class="item item-avatar item-text-wrap">
    <img ng-src="http://placehold.it/65x65">
    <h2>{{modal.row.firstname}} {{modal.row.lastname}}</h2>
    <p>{{modal.row.jobtitle}}</p>
</div>

<a href="tel:{{modal.row.phone}}" class="item item-icon-left">
    <i class="icon ion-iphone"></i>
    {{modal.row.phone}}
</a>

<a href="mailto:{{modal.row.email}}" class="item item-icon-left">
    <i class="icon ion-email"></i>
    {{modal.row.email}}
</a>         

I've test it in your codepen and it works. Try it and tell me if it works for you.

Upvotes: 2

Related Questions