0

I am trying to use a lazyLoad directive in another directive. The problem is I cannot figure out how to call the 'loadMore' function in the Controller as it never fires.

Here is the Main Directive:

    angular.module('ssq.shared').directive('checkboxPicklist', function() {
    return {
        restrict: 'E',
        templateUrl: '/SSQV4/SSQV5/Scripts/app/Shared/directives/checkboxPicklist.html',
        replace: true,
        scope: {
            itemId: '=',
            list: '=',
            nameProp: '=',
            title: '@',
            searchPlaceholder: '@',
            callbackFn: '&'
        },
        link: function (scope, element, attrs) {
            scope.query = '';

            var child = element.find('.dropdown-menu');
            child.on({
                'click': function(e) {
                    e.stopPropagation();
                }
            });

            var selectedItemFn = function (item) {
                return item.selected;
            };

            scope.getSelectedCount = function() {
                return _.filter(scope.list, selectedItemFn).length;
            };

            scope.allSelected = function(list) {
                var newValue = !scope.allNeedsMet(list);
                _.each(list, function(item) {
                    item.selected = newValue;
                    scope.callbackFn({ object: item });
                });
            };

            scope.allNeedsMet = function(list) {

                var needsMet = _.reduce(list, function(memo, item) {
                    return memo + (item.selected ? 1 : 0);
                }, 0);
                if (!list) {
                    return (needsMet === 0);
                }
                return (needsMet === list.length);
            };
        }
    };
});

})();

Here is the lazyLoad Directive:

app.directive('lazyLoad', function () {
return {
    restrict: 'A',
    scope: { 'loadMore': '&' },
    link: function (scope, elem) {
        var scroller = elem[0]
        $(scroller).bind('scroll', function () {
            if (scroller.scrollTop + scroller.offsetHeight >= scroller.scrollHeight) {
                scope.$apply('loadMore()')
            }
        })
    }
}

});

Here is my Controller Function:

    $scope.loadMore = function () {
    indServices = indServices + 10
    var r = 10
    if (ind + 10 >= $scope.buffer.Services.length) {
        r = $scope.buffer.Services.length - ind
    }

}

Here is my HTML:

<div class="pec-checkbox-picklist btn-group btn-group-picklist">
<button id="{{itemId}}" class="form-control dropdown-toggle" data-toggle="dropdown">
    <span class="cbpl-btn-text">{{ getSelectedCount() }} {{ title }}</span><span class="caret"></span>

</button>
<ul class="dropdown-menu dropdown-menu-complex" data-complex-menu style="overflow-y: scroll" lazy-load>

    <li class="list-group-item search-item">
        <input class="form-control" type="text" placeholder="{{ searchPlaceholder }}" ng-model="query" />
        <button type="button" class="btn btn-small" ng-show="query" ng-click="query = undefined">clear</button>
    </li>
    <li class="divider" ng-hide="query"></li>
    <li class="list-group-item" ng-hide="query">
        <label class="checkbox">
            <input type="checkbox" ng-click="allSelected(list)" ng-checked="allNeedsMet(list)">
            Select All
        </label>
    </li>
    <li class="divider"></li>
    <li class="list-group-item" ng-repeat="item in list | searchFilter:nameProp:query">
        <label class="checkbox" title="{{ item[nameProp] }}">
            <input type="checkbox" ng-model="item.selected" ng-change="callbackFn({object: item})">
            {{ item[nameProp] }}
        </label>
    </li>

</ul>

When the lazyLoad directive hits scope.$apply('loadMore()) it never executes the function as it sees the other directive "checkboxPicklist" as the parent scope. Any assistance is greatly appreciated!

2 Answers 2

1

lazy-load directive doesn't have load-more attribute. loadMore method from parent scope isn't passed to it. It should be used with

<... lazy-load load-more="loadMore()">
Sign up to request clarification or add additional context in comments.

Comments

0

This required changes in the parent directive js file, the parent directive html file, and the parent html page. In the html template of the parent directive, I had to add load-more="loadMore()" on the line with the lazyload directive. So it looks like this:

   <div class="pec-checkbox-picklist btn-group btn-group-picklist">
    <button id="{{itemId}}" class="form-control dropdown-toggle" data-toggle="dropdown">
        <span class="cbpl-btn-text">{{ getSelectedCount() }} {{ title }}</span><span class="caret"></span>

    </button>
    <ul class="dropdown-menu dropdown-menu-complex" data-complex-menu style="overflow-y: scroll" lazy-load load-

more="loadMore()">
        <li class="list-group-item search-item">
            <input class="form-control" type="text" placeholder="{{ searchPlaceholder }}" ng-model="query" />
            <button type="button" class="btn btn-small" ng-show="query" ng-click="query = undefined">clear</button>
        </li>
        <li class="divider" ng-hide="query"></li>
        <li class="list-group-item" ng-hide="query">
            <label class="checkbox">
                <input type="checkbox" ng-click="allSelected(list)" ng-checked="allNeedsMet(list)">
                Select All
            </label>
        </li>
        <li class="divider"></li>
        <li class="list-group-item" ng-repeat="item in list | searchFilter:nameProp:query">
            <label class="checkbox" title="{{ item[nameProp] }}">
                <input type="checkbox" ng-model="item.selected" ng-change="callbackFn({object: item})">
                {{ item[nameProp] }}
            </label>
        </li>
    </ul>
</div>

However, calling loadMore() here just switched the scope to the parent directive. It still did not hit the function in the main controller. So, to it, I then had to add call-More():

    scope: {
        itemId: '=',
        list: '=',
        nameProp: '=',
        title: '@',
        searchPlaceholder: '@',
        callbackFn: '&',
        callMore: '&'
    },
            scope.loadMore = function () {
            scope.callMore();
        };

Then to the Html page where that directive is used, I had to add call-more="loadMore()" to actually finally hit the $scope.loadMore function in my main controller. Because the directive is a repeat, I had to add a specific loadMore() to each picklist as below:

    scope.loadMoreServices = function () {
        indServices = indServices + 10;
        var r = 10;
        if (indServices + 10 >= $scope.buffer.Services.length) {
            r = $scope.buffer.Services.length - indServices;
        }
        $scope.services = $scope.services.concat($scope.buffer.Services.slice(indServices, r + indServices));
    };
    $scope.loadMoreAreas = function () {
        indAreas = indAreas + 10;
        var r = 10;
        if (indAreas + 10 >= $scope.buffer.Areas.length) {
            r = $scope.buffer.Areas.length = indAreas;
        }
        $scope.areas = $scope.areas.concat($scope.buffer.Areas.slice(indAreas, r + indAreas));
    };
    $scope.loadMoreVerifications = function () {
        indVerifications = indVerifications + 10;
        var r = 10;
        if (indVerifications + 10 >= $scope.buffer.Verifications.length) {
            r = $scope.buffer.Verifications.length = indVerifications;
        }
        $scope.verifications = $scope.verifications.concat($scope.buffer.Verifications.slice(indVerifications, r + 

indVerifications));
    };
    $scope.loadMoreSubscriptions = function () {
        indSubscriptions = indSubscriptions + 10;
        var r = 10;
        if (indSubscriptions + 10 >= $scope.buffer.Subscriptions.length) {
            r = $scope.buffer.Subscriptions.length = indSubscriptions;
        }
        $scope.subscriptions = $scope.subscriptions.concat($scope.buffer.Subscriptions.slice(indSubscriptions, r + 

indSubscriptions));
    };

    $scope.$watch('buffer', function () {
        indServices = 0;
        indAreas = 0;
        indVerifications = 0;
        indSubscriptions = 0;
        $scope.services = $scope.buffer.Services.slice(0, 10);
        $scope.areas = $scope.buffer.Areas.slice(0, 10);
        $scope.verifications = $scope.buffer.Verifications.slice(0, 10);
        $scope.subscriptions = $scope.buffer.Subscriptions.slice(0, 10);
    });

The finished HTML on the Main page:

<checkbox-picklist data-item-id="'servicesPicklist'"
                                                       data-search-placeholder="Search Services"
                                                       data-list="services"
                                                       data-title="Service(s)"
                                                       data-name-prop="'vchDescription'"
                                                       data-callback-fn="addService(object)"
                                                       call-more="loadMoreServices()">

                                    </checkbox-picklist>
                                </div>
                                <div class="col-sm-6 col-md-6 col-lg-3">
                                    <checkbox-picklist data-item-id="'areasPicklist'"
                                                       data-search-placeholder="Search Areas"
                                                       data-list="areas"
                                                       data-title="State(s)/Province(s)"
                                                       data-name-prop="'vchStateLongName'"
                                                       data-callback-fn="addArea(object)"
                                                       call-more="loadMoreAreas()">
                                    </checkbox-picklist>
                                </div>
                                <div class="col-sm-6 col-md-6 col-lg-3">
                                    <checkbox-picklist data-item-id="'verificationsPicklist'"
                                                       data-search-placeholder="Search Verifications"
                                                       data-list="verifications"
                                                       data-title="Verification(s)"
                                                       data-name-prop="'vchDescription'"
                                                       data-callback-fn="addVerification(object)"
                                                       call-more="loadMoreVerifications()">
                                    </checkbox-picklist>
                                </div>
                                <div class="col-sm-6 col-md-6 col-lg-3">
                                    <checkbox-picklist data-item-id="'subscriptionsPicklist'"
                                                       data-search-placeholder="Search Subscriptions"
                                                       data-list="subscriptions"
                                                       data-title="Subscription(s)"
                                                       data-name-prop="'vchDescription'"
                                                       data-callback-fn="addSubscription(object)"
                                                       call-more="loadMoreSubscriptions()">
                                    </checkbox-picklist>

Thanks Estus, as your response helped to put me on the correct path. I hope I explained this well enough to help someone else. Happy coding!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.