【问题标题】:AngularJS factory with $http and multiple controllers带有 $http 和多个控制器的 AngularJS 工厂
【发布时间】:2015-10-28 09:48:07
【问题描述】:

我希望多个控制器能够使用带有 $http 的工厂更新附加到一个控制器的单个视图。

我的列表视图:

<div class="list" ng-repeat="image in images" ng-controller="controller1">
   <div lass="item"><img src="{{image.url}}" /></div>
</div>

服务:

.factory("imageService", function($http) {
  return {
    getImages: function() {
      return $http({
        method: "get",
        url: "http://example.com/images",
        params: { user: window.localStorage['user_id'] }
      })
    }
  }
});

控制器 1:

.controller('controller1', function($scope, imageService) {
   window.localStorage['user_id'] = '101';
   var handleSuccess = function(data, status) {
       $scope.images = data;
   };
   imageService.getImages().success(handleSuccess);
})

这一切都有效。加载应用后,列表会立即填充用户“101”的图像列表。

在另一个控制器中,我希望能够切换用户并使用新图像自动从控制器 1 重新填充视图中的图像列表。

控制器 2:

.controller('controller2', function($scope, imageService) {
   window.localStorage['user_id'] = '202';
   imageService.getImages();
})

所以控制器 2 将运行 getImages(),我可以看到 $http 请求通过 chrome 开发工具/XHR 工作。而且我知道为什么附加到 controller1 的列表视图没有填充,但我不知道如何填充它。我尝试将成功回调移动到服务中并在服务上设置“图像”属性并在控制器 1 中设置 $scope.images,但没有运气。

如何将新的图像列表强制添加到附加到控制器 1 的视图中?

【问题讨论】:

  • 您可以从 rootScope 向控制器发出一个事件,并且发出处理的侦听器从 imageService 加载图像。
  • @tafoo85 是否需要使用 $rootScope 来更新图像列表?
  • 不,我想不到快速两秒钟的解决方案。其他人的想法更好。

标签: angularjs


【解决方案1】:

您应该在服务中管理一个列表,您将绑定到您的controller1

.factory("imageService", function($http) {
    var service = {};
    service.images = {};
    service.images.list = [];
    service.getImages = function(userId) {
      window.localStorage['user_id'] = userId;
      return $http({
        method: "get",
        url: "http://example.com/images",
        params: { user: userId }
      }).success(function(data){
          service.images.list = data
      });
    }

  //at the initialization of the service, you launch the getImages once with the localStorage value.
  service.getImages(window.localStorage['user_id']);

  return service;
});

然后你可以在你的控制器中像这样绑定它:

.controller('controller1', function($scope, imageService) {
   $scope.images = imageService.images;
   //then access it in the view with images.list
   imageService.getImages(101);
})

.controller('controller2', function($scope, imageService) {
   $scope.images = imageService.images;
   //then access it in the view with images.list
   imageService.getImages(202);
})

请注意,使用子对象(images.list 而不是 images)很重要。

如果您想了解更多关于为什么需要此子对象的详细信息,您可以阅读 this answer 关于此主题的内容

希望对您有所帮助。

【讨论】:

  • 所以在视图中,ng-repeat="image in images.list"。这似乎运作良好。让我测试一下。
  • @lilbiscuit 集成效果如何?随时询问您是否需要帮助。这正是 ng-repeat 的样子。
  • @lilbiscuit 顺便说一句,你为什么不使用 var 和你的 get 函数而不是使用本地存储?
  • @Okazzari - 我使用 localStorage 来保存用户选择(这是一个移动混合应用程序)。
  • @lilbiscuit 我不确定我是否理解您的问题,但您可以将 user_id 本地存储管理到服务中。我将更新答案以说明如何。
【解决方案2】:

我认为您可以只使用一个控制器。例如,在某个时间点,用户单击某个按钮,重新加载图像列表并重新渲染视图以显示列表。

例如,将工厂设为:

.factory("imageService", function($http) {
  return {
    getImages: function(userId) {
      return $http({
        method: "get",
        url: "http://example.com/images",
        params: { user: userId }
      });
    }
  };
});

在控制器中:

.controller('imageController', function($scope, imageService) {

   function refreshImages (userId) {
     imageService.getImages(userId).success(function(data) {
       $scope.$apply(function () {
         $scope.images = data;
       });
     });
   }

   refreshImages('101');
   $scope.loadImages = function (userId) {
     refreshImages(userId);
   };
});

【讨论】:

  • 我需要能够从多个控制器中更新列表。
  • 好吧,如果两个控制器共享相同的作用域,则需要在获取新的图像列表后调用$scope.$apply
  • 我仍然无法想象你的场景。控制器不应该共享这种逻辑。您可以提取到服务/工厂或指令。
  • 场景是我的应用程序中的每个视图都有自己的控制器。一个视图/控制器显示图像列表。另一个视图/控制器显示用户列表。在控制器 2 视图中选择一个用户,然后查看所选用户控制器 1 视图的结果图像。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
相关资源
最近更新 更多