Collection-repeat errors

I want to report some errors, that I’ve noticed:

  1. If I use sub-header the first element in the list will be hidden:

  1. If I use ion-refresher and try to refresh I’ll get a gap in the bottom of the list ( some elements are not created):

  1. While scrolling, text isn’t binding in correct way ( I’ve got random characters):

  1. If I use ion-option and don’t hide it and then scroll, ion-option will be visible in incorrect item ( it’s not reset).

A code example (codepen or something else) would be nice to reproduce this behaviour.

Thank you.

This is my directive for list:

<ion-view title="{{vTitle}}">
<ion-nav-buttons side="right">
    <button ng-show="vAddVisibility" class="button button-icon icon ion-ios7-plus-empty" ng-click="vAdd()"></button>
    <button ng-show="vFilterVisibility" class="button button-clear icon ion-funnel" ng-click="vFilter()"></button>
</ion-nav-buttons>

<ion-header-bar ng-show="vSearchVisibility" class="bar bar-subheader item-input-inset">
    <label class="item-input-wrapper">
        <i class="icon ion-ios7-search placeholder-icon"></i>
        <input type="text" placeholder="Szukaj" ng-model="vQuery">
    </label>
    <button class="button button-icon icon ion-ios7-checkmark-empty" ng-click="vSearch({query: vQuery})"></button>
</ion-header-bar>

<ion-content class="has-header">
    <ion-refresher on-refresh="vRefresh()" refreshing-icon="ion-ios7-reloading" pulling-icon="ion-ios7-arrow-thin-down"></ion-refresher>
    <ion-list ng-transclude> </ion-list>
    <ion-infinite-scroll ng-if="vCanLoadMore()" on-infinite="vLoadMore()" distance="10%"></ion-infinite-scroll>
</ion-content></ion-view>

And usage:

<list-view v-title={{Title}}
             v-add-visibility="IsAddVisible" v-add="Edit()"
             v-filter-visibility="IsFilterVisible" v-filter="Filter()"
             v-search-visibility="IsSearchBarVisible" v-search="Search(query)"
             v-refresh="Refresh()"
             v-can-load-more="CanLoadMore()" v-load-more="LoadMore()">
<ion-item class="my-item"
     collection-repeat="item in List"
     collection-item-width="'100%'"
     collection-item-height="125"
     ng-style="{height: 125}"
     ng-click="ItemDetails(item)">
    <div class="row">
        <div class="col col-left" ng-show="item.Code">{{item.Code}}</div>
        <div class="col col-left-blank" ng-hide="item.Code">{{'-'}}</div>
        <div class="col col-right" ng-show="item.Name">{{item.Name}}</div>
        <div class="col col-right-blank" ng-hide="item.Name">{{'-'}}</div>
    </div>
    <div class="row">
        <div class="col col-left" ng-show="item.City">{{item.City}}</div>
        <div class="col col-left-blank" ng-hide="item.City">{{'-'}}</div>
        <div class="col col-right" ng-show="item.Street">{{item.Street}}</div>
        <div class="col col-right-blank" ng-hide="item.Street">{{'-'}}</div>
    </div>
    <div class="row">
        <div class="col col-left" ng-show="item.Nip">{{item.Nip}}</div>
        <div class="col col-left-blank" ng-hide="item.Nip">{{'-'}}</div>
        <div class="col col-right-blank">{{'-'}}</div>
    </div>
    <ion-option-button class="button-positive" ng-click="Edit(item)">Edytuj</ion-option-button>
</ion-item>

This is my controller responsible for loading list elements:

angular.module('app.Controllers')
.inheritController('ListController', 'DataController', function (base, $scope) {

    $scope.IsAddVisible = true;
    $scope.IsFilterVisible = false;
    $scope.IsSearchBarVisible = true;

    var m_list;

    this.Init = function(list){
        m_list = list;
        $scope.List = m_list.ToArray();
        m_list.Init();
    };

    $scope.Refresh = function () {
        m_list.Init();
        return m_list.LoadNextPage()
            .then(function(){
                $scope.$broadcast('scroll.refreshComplete');
            })
            .catch(function(e){
                $scope.$broadcast('scroll.refreshComplete');
                base.Alert(e);
            });
    };
    $scope.CanLoadMore = function(){
        return m_list.CanLoadNextPage();
    };
    $scope.LoadMore = function(){
         m_list.LoadNextPage()
            .then(function(){
                 $scope.$broadcast('scroll.infiniteScrollComplete');
             })
            .catch(function(e){
                 $scope.$broadcast('scroll.infiniteScrollComplete');
                 base.Alert(e);
             });
    };

    $scope.Search = function(query){
        m_list.SearchString = query;
        m_list.Init();
        m_list.LoadNextPage()
            .then(function(){
                $scope.$broadcast('scroll.refreshComplete');
                $scope.$broadcast('scroll.scrollTop');
            })
            .catch(function(e){
                $scope.$broadcast('scroll.refreshComplete');
                $scope.$broadcast('scroll.scrollTop');
                base.Alert(e);
            });
    };
    $scope.ShowFilters = function(){

    };
});

Do you have any ideas, if it’s my mistake or problem with collection-repeat?

A bunch of source code… maybe you can make a codepen of this, with some mocked data.

Why are you setting ng-style additional to the collection-item-height=“125”?
Are your m_list functions working correctly?

Like appending the loaded items to the current list and so on?

You have right ng-style isn’t neccesary. Yes, all stuff with loading data work correctly. There is only problem with displaying data.
1, 2, 4 appear, when I test app in the browser.
3 exists only on my device ( LG Swift L5, Android 4.1.2)

What is more:
1 - This could be my mistake with using sub-header with collection-repeat ( or list, generally). Maybe you could look at my html directive?
2 - This is evident problem with working collection-repeat and ion-refresher at the same time
3 - This one i strange, maybe it depends on system or device.
4 - This is mistake of collection-repeat’s creator. If I use item with ion-option and I swipe it then I scroll list without swipe againg to hidden, it’ll visible in the next part of list in wrong item.

Has anyone any idea, why I’va got this errors? I’ve checked, that collection-repeat even without sub-header in view hides the first element like on the first screenshot.

The problem is:

you are showing the subheader only if a condition is true (vSearchVisibility).
On your ion-content you set always the class has-header (that should not be necessary, if the real header is always visible).

But you have to add ng-class to you ion-content to add ‘has-subheader’ class if the condition of your subheader is true.

With your code. your ion-content is always behind your subheader, because this class is not set correctly.

I’ve checked your advices and I agree, that ion-content doesn’t need ‘has-header’ class. The point is that even without search bar ( in the subheader) the first element is not visible. So how this class should be set?

Strange for my purposes i only added the has-subheader class conditionally.

A codepen would be very nice to check style settings and so on.
Maybe you could build an example.

Thank you.

I recognized some bugs as well.

As soon as I remove the ion-refresher the list works again. When I use the ng-repeat instead of the collection-repeat there is no problem as well.

Have a look at my pen: http://codepen.io/niwen/pen/ikyxv

any update?


I have noticed the same issue - the last card in my listing is rendered blank when using an ion-refresher AND collection repeat directives - similar to

<ion-content delegate-handle="mainScroll">
   <ion-refresher
           skipContent="true"
            pulling-text="Pull to refresh..."
            on-refresh="doRefresh()">
    </ion-refresher>
    <ion-infinite-scroll
            ng-show="canGetMore()"
            ng-if="canGetMore()"
            on-infinite="loadMore()"
            distance="1">
    </ion-infinite-scroll>
    <ion-list class="list list-inset">
        <ion-item class="item my-item card-container"
                  collection-repeat="post in postsqueue"
                  collection-item-height="280"
                  href="#/postdetail/{{post.id}}">

As soon as i remove the ion-refresher things are fine. Digging further, this looks like it is caused in part by the mechanisms that determine ‘beforeSiblings’ and ‘afterSiblings’ in the collection-repeat directive’s rerender function.

I am not at all saying below is the way to fix this - but I can get things to be fine if i modify the beforeSiblings push logic in the rerender function:

  function rerender(value) {
    var beforeSiblings = [];
    var afterSiblings = [];
    var before = true;
    forEach(scrollViewContent.children, function(node, i) {
      if ( ionic.DomUtil.elementIsDescendant($element[0], node, scrollViewContent) ) {
        before = false;
      } else {
        var width = node.offsetWidth;
        var height = node.offsetHeight;
        if (width && height) {
          var element = jqLite(node);
          //CHANGED - don't include a scroll refresher - causes extra an card in listing
          if(element[0].className !== "scroll-refresher"){
              (before ? beforeSiblings : afterSiblings).push({
                width: node.offsetWidth,
                height: node.offsetHeight,
                element: element,
                scope: element.isolateScope() || element.scope(),
                isOutside: true
              });
          }
        }
      }
    });

    scrollView.resize();
    dataSource.setData(value, beforeSiblings, afterSiblings);
    collectionRepeatManager.resize();
  }
1 Like

looks like some of the issues described in this thread are repaired with

Should be out in Beta 12 it looks like

HTH,
RW

1 Like