【问题标题】:AngularJS: function from service don't work in ng-infinite-scoll directiveAngularJS:服务中的函数在 ng-infinite-scoll 指令中不起作用
【发布时间】:2023-03-28 12:29:01
【问题描述】:

我想使用 ng-infinite-scroll (https://sroze.github.io/ngInfiniteScroll/)。但是当我想从我的服务调用函数(注入控制器)时,什么也没发生(这个函数不会触发)。当我不是从服务而是从控制器的 $scope 调用函数时 - 一切正常。如何从无限滚动指令中的注入服务中调用函数?

我的 HTML 结构:

<div class="col-xs-12 publications-container" ng-controller="showPublicationsCtrl">
    <h3 class="publ-heading">Proposed Publications</h3>
    <ul class="list-group" infinite-scroll="publicationsFactory.getPublications()" infinite-scroll-disabled='publicationsFactory.busyLoadingData'>
      <li ng-repeat="publication in publications" class="list-unstyled list-group-item" ng-cloak>
        <p class="text-warning">Author: <i>{{publication.author}},   {{publication.timestamp | date: 'MMM. d, y'}}</i></p>
        <p ng-text-truncate="publication.text" ng-tt-words-threshold="3">{{publication.text}}</p>
        <p class="text-muted">Channels: <i>{{publication.channels.join(", ")}}</i></p>
      </li>
    </ul>
  </div>

我的showPublicationsCtrl 控制器:

twitterApiApp.controller("showPublicationsCtrl", ['publicationsFactory', '$scope', function (publicationsFactory, $scope) {
  publicationsFactory.getPublications();
  $scope.publications = publicationsFactory.publications;
}]);

我的publicationsFactory 服务:

angular.module('twitterApiApp').factory('publicationsFactory', ['$http', function($http) {
  var publicationsFact = {};
  publicationsFact.publications = [];
  publicationsFact.busyLoadingData = false;

  publicationsFact.getId = function() {
publicationsFact.id = publicationsFact.publications.length > 0 ?
                      publicationsFact.publications[publicationsFact.publications.length-1]['id'] : 0;
  };

  publicationsFact.getPublications = function () {
    console.log("Triggered");
    if (publicationsFact.busyLoadingData) return;
    publicationsFact.busyLoadingData = true;
    publicationsFact.getId();
    $http.get("/Publications?id_gte=" + publicationsFact.id + "&_limit=2").then(function(response) {
      for (var i = 0; i < response.data.length; i++) {
        publicationsFact.publications.push(response.data[i]);
      };
    });
    publicationsFact.busyLoadingData = false;
  };
  return publicationsFact;
}]);

如果我在我的控制器中创建一些函数,例如$scope.myFunction,然后在 HTML 结构中我将infinite-scroll 属性分配给myFunction(),该函数将成功执行。所以,我认为我在控制器中注入服务的方式可能存在一些错误。但是除了 ng-inginite-scroll 之外的其他所有东西都按计划工作。

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope angular-services nginfinitescroll


    【解决方案1】:

    infinite-scroll 绑定到 $scope.publicationsFactory :

    <ul class="list-group" infinite-scroll="publicationsFactory.getPublications()" infinite-scroll-disabled='publicationsFactory.busyLoadingData'>
    

    publicationsFactory 在您的范围内不可用,您必须像这样公开它:

    twitterApiApp.controller("showPublicationsCtrl", ['publicationsFactory',  '$scope', function (publicationsFactory, $scope) {
        // Expose publication factory
        $scope.publicationsFactory = publicationsFactory;
    
        publicationsFactory.getPublications();
        $scope.publications = publicationsFactory.publications;
    }]);
    

    如何使用 Factory 检索到的最新出版物更新 $scope.publications

    你的工厂可以返回一个用最新出版物解决的承诺,像这样更改你的代码:

    angular.module('twitterApiApp').factory('publicationsFactory', ['$http', '$q', function($http, $q) {
        var publicationsFact = {};
        publicationsFact.publications = [];
        publicationsFact.busyLoadingData = false;
    
    
        publicationsFact.getId = function() {
            publicationsFact.id = publicationsFact.publications.length > 0 ?
                publicationsFact.publications[publicationsFact.publications.length - 1]['id'] : 0;
        };
    
        /**
         * Get latest publications
         * @returns {object} A promise
         */
        publicationsFact.getPublications = function() {
            var deferred = $q.defer();
    
            console.log("Triggered");
            if (publicationsFact.busyLoadingData) return;
            publicationsFact.busyLoadingData = true;
            publicationsFact.getId();
            $http.get("/Publications?id_gte=" + publicationsFact.id + "&_limit=2").then(function(response) {
                for (var i = 0; i < response.data.length; i++) {
                    publicationsFact.publications.push(response.data[i]);
                };
                // Resolve promise with updates publications list
                deferred.resolve(publicationsFact.publications);
            }, function(error) {
                // Reject promise with error message
                deferred.reject(error.message);
            });
            publicationsFact.busyLoadingData = false;
    
            // Return promise
            return deferred.promise;
    
        };
        return publicationsFact;
    }]);
    

    然后,在您的控制器中:

    twitterApiApp.controller("showPublicationsCtrl", ['publicationsFactory',  '$scope', function (publicationsFactory, $scope) {
        // Expose publication factory
        $scope.publicationsFactory = publicationsFactory;
    
        publicationsFactory.getPublications()
        .then(function(results) {
            $scope.publications = results;
        });
    }]);    
    

    【讨论】:

    • 是的,我认为它会起作用,但是如果我的publicationsFactory.publications 中有一些更新,它们会自动显示在视图中吗?
    • 如您所见,我从publications 数组动态地在我的html 结构中创建了一个列表。在我页面的另一个地方,我创建了一个表单,允许用户将新项目添加到publications 数组以及将新项目添加到服务器上的数据库中。如果我在控制器中公开发布工厂,当用户添加新项目时视图是否会自动更新?
    • 不,如果不向"/Publications 提出新请求,就无法自动更新 $scope 出版物 :)
    • 但是在服务器端,一旦发布了新评论,您可以发送一个包含新发布的新 WebSocket 事件,然后在客户端将其附加到 $scope.publications 的正确位置,具体取决于发布日期。
    • 为此,您必须在服务器端打开 WebSocket 通道并在客户端订阅它
    【解决方案2】:

    您应该将此行添加到您的 ctrl:

    $scope.getPublications = publicationsFactory.getPublications;
    

    然后从视图中调用该 ctrl 函数。 这样,您将对服务函数的引用绑定到视图中可用的控制器范围。

    编辑:另一种选择是将整个服务绑定到 ctrl 属性,就像其他人已经建议的那样

    【讨论】:

    • 好的,还有什么更好的选择?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 2019-03-10
    • 2015-07-26
    • 1970-01-01
    相关资源
    最近更新 更多