从嵌套指令中的链接函数调用控制器函数

Call Controller Function from link function in Nested Directive

本文关键字:函数调用 控制器 函数 链接 嵌套 指令      更新时间:2023-09-26

我正试图在另一个指令中使用lazyLoad指令。问题是,我不知道如何调用Controller中的"loadMore"函数,因为它从不启动。

以下是主要指令:

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

})();

这是lazyLoad指令:

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

});

这是我的控制器功能:

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

这是我的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>

当lazyLoad指令命中scope.$apply('loadMore())时,它从不执行该函数,因为它将另一个指令"checkboxPicklist"视为父作用域。非常感谢您的帮助!

lazy-load指令没有load-more属性。父作用域中的loadMore方法没有传递给它。它应该与一起使用

<... lazy-load load-more="loadMore()">

这需要更改父指令js文件、父指令html文件和父html页面。在父指令的html模板中,我必须在带有lazylod指令的行上添加load-more="loadMore()"。看起来是这样的:

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

然而,在这里调用loadMore()只是将作用域切换到父指令。它仍然没有达到主控制器中的功能。因此,我不得不添加call-More():

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

然后,在使用该指令的Html页面上,我必须添加call-more="loadMore()",才能真正达到主控制器中的$scope.loadMore函数。因为指令是重复的,所以我必须在每个选择列表中添加一个特定的loadMore(),如下所示:

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

主页上完成的HTML:

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

谢谢Estus,因为你的回复帮助我走上了正确的道路。我希望我解释得足够好,能帮助其他人。编码快乐!