javascriptangularjsiscroll

Ng-repeat and iScroll dynamic width not working


I have a solution that contains an ng-repeat within another ng-repeat. I use this to create two tables with both static content and dynamic content. At first load the scroll doesnt work. Once you resize the page with the content, the scroll works fine. On iPad and Android tablets I have encountered that the scroll works at first load but the width doesnt contains the last two static TD's in the table.

I am pretty sure that the solution is to setup a correct .refresh method for iScroll but I cannot figure out the correct setup.

I have tried using the ng-iScroll plugin but without any luck. I have also tried to put in a timeout for the .refresh method but still with no result.

I was able to reconstruct the problem with this fiddle: jsfiddle.net/8BUjf/115/

When you run the fiddle the scroll doesnt work. Once you resize the content page just a little bit the scroll works fine with a correct width that contains all static and dynamic td's.

The following code is also found in the fiddle above.

EDIT

After the answer from steppefox I tried to setup the solution with the directive. I am now getting 0 errors in the consol and the angular shows the list correctly but the scroll still doesnt work - even if I try to resize the content.

Here is the new fiddle http://jsfiddle.net/8BUjf/149/ and the code below is also updated.

My HTML

<div ng-app="app">
<div ng-controller="TodoCtrl">
<div class="tfl-overflow" id="iscrollwrapper" iscrollDirective>
<div id="iscroller">
            <table class="table" style="border-bottom: 1px solid #E77E23; ">
                <tr>
                    <td>
                        <h3 class="text-width">
                            <a href="">Static TD 1</a>
                        </h3>
                    </td>
                    <td ng-repeat="parentCategory in totalParentCategoriesCount" class="text-info">
                        <h3 class="text-width">
                            <a href="">Dynamic TD {{parentCategory.count}}</a>
                        </h3>
                    </td>
                    <td>
                        <div>
                            <h3 class="text-width">
                                <a href="">Static TD 2</a>
                            </h3>
                        </div>
                    </td>
                    <td>
                        <div>
                            <h3 class="text-width">
                                <a href="">Static TD 3</a>
                            </h3>
                        </div>
                    </td>
                </tr>
            </table>
            <table class="table table-striped">
                  <tr ng-repeat="fighter in totalFighterList">
                    <td>
                        <p class="text-width">Static TD</p>
                    </td>
                    <td ng-repeat="parentCategory in totalParentCategoriesCount">
                        <p class="text-width">Dynamic TD {{parentCategory.count}}</p>
                    </td>
                    <td>
                        <p class="text-width">Static TD 2</p>
                    </td>
                    <td>
                        <p class="text-width">Static TD 3</p></td>
                  </tr>
            </table>
        </div>
    </div>
</div>
</div>

Angular

var mainApp = angular.module("app", []);

mainApp.directive('iscrollDirective', iscrollDirective);
iscrollDirective.$inject = ['$timeout'];
function iscrollDirective($timeout) {
return {
    restrict:'A',
    link: function ($scope, element, attrs) {
        $timeout(function(){
            var iscrollwrapper = new IScroll(element.attr('#iscrollwrapper'), {
                scrollX: true,
                scrollY: false,
                mouseWheel: false,
                scrollbars: false,
                useTransform: true,
                useTransition: false,
                eventPassthrough: true,
            });
            iscrollwrapper.refresh();
        })
    }
}
};

mainApp.controller('TodoCtrl', function($scope) {
$scope.totalParentCategoriesCount = [
    {count:1},
    {count:2},
    {count:3},
    {count:4},
    {count:5},
    {count:6}];

$scope.totalFighterList = [
    {count:1},
    {count:2},
    {count:3},
    {count:4},
    {count:5},
    {count:6}];
});

CSS

#iscroller{
display:inline-block;
width:auto;
}

.text-width{
width:150px;
}

.tfl-overflow {
overflow-x: auto !important;
-webkit-overflow-scrolling: touch;
}

#iscrollwrapper{
width:100%;
}

Solution

  • The problem is, because iScroll was runned earlier than ng-repeat had run by angular.

    1. Create an angular directive

      angular.module('app').directive('iscrollDirective', iscrollDirective); iscrollDirective.$inject = ['$timeout']; function iscrollDirective($timeout) { return { restrict:'A', link: function ($scope, element, attrs) { $timeout(function(){ iscrollwrapper = new IScroll(element.attr('id'), { scrollX: true, scrollY: false, mouseWheel: false, scrollbars: false, useTransform: true, useTransition: false, eventPassthrough: true, }); iscrollwrapper.refresh(); }) } } });

    2. Remove your JS code of calling iscroll in function loaded, cuz it's useless now (we have directive for that).

    3. Add to your wrapper <div class="tfl-overflow" id="iscrollwrapper"> attribute iscroll-directive, like that <div class="tfl-overflow" id="iscrollwrapper" iscroll-directive>

    UPDATE 2015-08-03

    http://jsfiddle.net/8BUjf/160 - fixed fiddle