Collection-repeat errors


#1

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

CollectionRepeat missing first item
#2

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

Thank you.


#3

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>

#4

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?


#5

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?


#6

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.


#7

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.


#8

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.


#9

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?


#10

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.


#11

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


CollectionRepeat missing first item
#12

any update?



#13

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

#14

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

Should be out in Beta 12 it looks like

HTH,
RW