Collection-Repeat + $ionicModal (Strange Behavior)


#1

Hi Folks,

My app is a company directory that uses Collection-Repeat to create roughly 200 list items. Each list item has a ng-click to open a Modal. This worked great when I was using ng-repeat, but now it is creating a strange behavior…

The phone displays roughly 5 list items on the viewport. If I were to click on the top list item to open the modal, it instead opens a modal for the bottom list item (bottom of the viewport, so item #5). When I click on item #2, it opens a modal for item #4, when I click #3 the modal doesn’t open. I’m not getting any errors in the console so it has me scratching my head.

Any ideas? Here is my code:

<ion-content>     
   <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}">          
     
    <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>                 
</ion-content>

Here is the controller code:

app.controller('IntroCtrl', function($scope, $ionicScrollDelegate, $ionicSideMenuDelegate) { 

      var contacts = $scope.contacts = [];
      var currentDepartment = '';
      var dep_listing = angular.fromJson(window.localStorage['data']);

      dep_listing.sort(function(a, b) {
          return a.department > b.department ? 1 : -1;
      })

      .forEach(function(dep) {            
          if(currentDepartment != dep.department) {
            contacts.push({
              isLetter: true,
              title: dep.department
            });  
            currentDepartment = dep.department;
          }         
          contacts.push(dep);
      });

      $scope.getItemHeight = function(row) {
        return row.isLetter ? 40 : 77;
      }; 

    };
});

Here is the modal template:

<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>

<button class="button button-block button-lsi" ng-click="closeModal()">Close Popup</button>

</ion-content>

And then of course the basic Modal Controller:

app.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();
  });
    
});

#2

Looking closely at the screen, I notice that initially (when the modal appears at the bottom before animating) the correct data is being displayed. The data inside the modal then changes as it animates to the resting position in the middle of the screen.

Any ideas as to why the modal data would change randomly? Is there a better way to link the “binding” between ng-click and modal contents? Does this indicate some issue with the scope?

EDIT - I added a second ng-click event to each list item and found some interesting results. Clicking on the element itself opens the modal with the incorrect data. Clicking on the button opens TWO modals (stacked) but they BOTH have the correct data. Removing either ng-controller or ng-click sends me back to square one with neither solution working. What is going on?

Here is the code:

<div class="list">
   <a class="item my-item"
              
      collection-repeat="row in alpha"
      collection-item-height="getItemHeight(row)"
      collection-item-width="'100%'"
      ng-class="{'item-divider': row.isLetter}"
      ng-controller="ModalCtrl" ng-click="modal.show();">
                
      <button ng-if="!row.isLetter" ng-controller="ModalCtrl" ng-click="modal.show();">Button</button>
                
      <img 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> 

(I’ve got my boss breathing down my neck so I’ve got to figure this out soon).

Thanks!

LSI


#3

Any chance you could throw an example of this in a codepen?


#4

Hi @mhartington,

See the Pen Chqjd by Justin Phillips (@Phillips126) on CodePen.

It’s stripped of some of my CSS so it isn’t as pretty as the actual product.

Thank you for your help!

LSI


#5

I just wanted to report back with a solution I got from Stack Overflow incase anyone runs into a similar problem: http://stackoverflow.com/questions/26611773/ionic-collection-repeat-and-ionicmodal-strange-behavior/26625444#26625444

What was happening was that I wasn’t passing data appropriately to my modal template.
I had to change my ng-click to:

ng-click="openModal(row);"

change my modal controller to:

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

and then access the data in my modal

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

...

#6

Hey sorry, been crazy busy.

Glad to see you were able to resolve the issue!