在角度,如何通过JSON对象/数组指令? [英] In Angular, how to pass JSON object/array into directive?

查看:189
本文介绍了在角度,如何通过JSON对象/数组指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我的应用程序有一个控制器,通过他们使用NG-REPEAT接受一个JSON文件,然后进行迭代。这是所有伟大的工作,但我也有一个需要通过同一个JSON文件要迭代的指令。这是摆在一个问题,因为我不能要求相同的JSON文件两次在一个页面上(我也不会要,因为这将是低效的)。无论是指令和控制要求,并通过JSON数据迭代就好了,如果我改变JSON文件之一的文件名。

我想知道的是:什么是去了解经过从我的控制器的JSON请求到指令形成阵列的最佳方式?我怎么可以在阵列传递到我的指令,并遍历时,我已经通过我的控制器访问它?

控制器

  appControllers.controller('dummyCtrl',函数($范围,$ HTTP){
   $ http.get('位置/ locations.json')。成功(功能(数据){
      $ scope.locations =数据;
   });
});

HTML

 < UL类=清单>
   <李NG重复=的地点位置>
      &所述; A HREF =#> {{location.id}}。 {{location.name}}&下; / A>
   < /李>
< / UL>
<地图和GT;< /图> //执行JS库

指令(工作时,我使用的文件名之外locations.json,因为我已经申请过一次

  .directive('地图',函数($ HTTP){
   返回{
     限制:'E',
     更换:真实,
     模板:'< D​​IV>< / DIV>,
     链接:功能(范围,元素,ATTRS){$ http.get('位置/ locations.json')。成功(功能(数据){
   angular.forEach(data.locations,功能(位置,键){
     //做一点事
   });
});


解决方案

如果你想跟着所有的最佳实践,有几件事情,我建议,其中一些触及在其他的答案和评论这个问题。


首先,虽然它并没有太多的关于你问的具体问题的影响,您没有提到效率,并在你的应用程序来处理共享数据的最佳方式是因素它变成一种服务。

我个人建议拥抱AngularJS的承诺制,这将使你的异步服务更可组合相比,生回调。幸运的是,角的 $ HTTP 服务已使用它们的引擎盖下。下面是一个将返回解析,从JSON文件中的数据的承诺的服务;调用服务不止一次不会造成第二HTTP请求。​​

app.factory('位置',函数($ HTTP){
  VAR承诺= NULL;  返回功能(){
    如果(承诺){
      //如果我们已经要求这一次数据,
      //返回已经存在的承诺。
      返回的承诺;
    }其他{
      答应= $ http.get('位置/ locations.json');
      返回的承诺;
    }
  };
});


至于获取数据到你的指令,需要记住的是指令的目的是抽象的通用DOM操作是很重要的;你应该的的应用程序特定的服务注入其中。在这种情况下,很容易将其简单地注入地点服务为指令,但是这对夫妻的指令,该服务。


  

在一旁code模块化简要:指令的功能几乎很少被负责获取或格式化自己的数据。没有什么从使用$ HTTP服务从指令中阻止你的,但是这是几乎总是错的事情。写控制器使用$ HTTP是做正确的方式。一个指令已经触及一个DOM元素,这是一个非常复杂的对象,很难存根出进行测试。添加网络I / O的组合使你的code,它更难理解和更难测试。此外,网络I / O锁在你的指令会得到其数据的方式 - 也许在其他地方,你会希望有这个指令从套接字接收数据,或在preloaded数据。你的指令应任取数据在通过范围的属性。$的eval和/或具有一个控制器来处理获取并存储所述数据


  
  

- <一href=\"http://the$c$cbarbarian.word$p$pss.com/2013/09/23/the-8020-guide-to-writing-angularjs-directives/\">The 80/20写作指南AngularJS指令


在这个特定的情况下,你应该把你的控制器的范围内适当的数据,并通过一个属性指令共享。

app.controller('SomeController',函数($范围,地点){
  位置()。成功(功能(数据){
    $ scope.locations =数据;
  });
});

&LT; UL类=清单&GT;
   &LT;李NG重复=的地点位置&GT;
      &所述; A HREF =#&GT; {{location.id}}。 {{location.name}}&下; / A&GT;
   &LT; /李&GT;
&LT; / UL&GT;
&LT;地图位置='位置'&GT;&LT; /图&GT;

app.directive('地图',函数(){
  返回{
    限制:'E',
    更换:真实,
    模板:'&LT; D​​IV&GT;&LT; / DIV&GT;,
    范围: {
      //你的指令创建范围的变量
      //叫做`locations`势必任何传递
      //在通过`在DOM locations`属性
      位置:'=位置
    },
    链接:功能(范围,元素,ATTRS){
      范围。$腕表('位置',函数(地区){
        angular.forEach(位置,功能(位置,键){
          // 做一点事
        });
      });
    }
  };
});

该指令不硬$ C $ -

在这种方式中,地图指令可以使用​​的任何的设置位置数据的使用CD使用特定的数据集,而只需把它放置在DOM将不会触发了随机HTTP请求连接的指令。

Currently, my app has a controller that takes in a JSON file then iterates through them using "ng-repeat". This is all working great, but I also have a directive that needs to iterate through the same JSON file. This is posing a problem as I cannot request the same JSON file twice on one page (nor would I want to because it would be inefficient). Both the directive and controller request and iterate through the JSON data just fine if I change the filename of one of the JSON files.

What I'm wondering is: what's the best way to go about passing the array formed from my controller's JSON request into the directive? How can I pass the array into my directive and iterate through when I've already accessed it via my controller?

Controller

appControllers.controller('dummyCtrl', function ($scope, $http) {
   $http.get('locations/locations.json').success(function(data) {
      $scope.locations = data;
   });
});

HTML

<ul class="list">
   <li ng-repeat="location in locations">
      <a href="#">{{location.id}}. {{location.name}}</a>
   </li>
</ul>
<map></map> //executes a js library

Directive (Works when I use a file name besides locations.json, since I've already requested it once

.directive('map', function($http) {
   return {
     restrict: 'E',
     replace: true,
     template: '<div></div>',
     link: function(scope, element, attrs) {

$http.get('locations/locations.json').success(function(data) {
   angular.forEach(data.locations, function(location, key){
     //do something
   });
});

解决方案

If you want to follow all the "best practices," there's a few things I'd recommend, some of which are touched on in other answers and comments to this question.


First, while it doesn't have too much of an affect on the specific question you asked, you did mention efficiency, and the best way to handle shared data in your application is to factor it out into a service.

I would personally recommend embracing AngularJS's promise system, which will make your asynchronous services more composable compared to raw callbacks. Luckily, Angular's $http service already uses them under the hood. Here's a service that will return a promise that resolves to the data from the JSON file; calling the service more than once will not cause a second HTTP request.

app.factory('locations', function($http) {
  var promise = null;

  return function() {
    if (promise) {
      // If we've already asked for this data once,
      // return the promise that already exists.
      return promise;
    } else {
      promise = $http.get('locations/locations.json');
      return promise;
    }
  };
});


As far as getting the data into your directive, it's important to remember that directives are designed to abstract generic DOM manipulation; you should not inject them with application-specific services. In this case, it would be tempting to simply inject the locations service into the directive, but this couples the directive to that service.

A brief aside on code modularity: a directive’s functions should almost never be responsible for getting or formatting their own data. There’s nothing to stop you from using the $http service from within a directive, but this is almost always the wrong thing to do. Writing a controller to use $http is the right way to do it. A directive already touches a DOM element, which is a very complex object and is difficult to stub out for testing. Adding network I/O to the mix makes your code that much more difficult to understand and that much more difficult to test. In addition, network I/O locks in the way that your directive will get its data – maybe in some other place you’ll want to have this directive receive data from a socket or take in preloaded data. Your directive should either take data in as an attribute through scope.$eval and/or have a controller to handle acquiring and storing the data.

- The 80/20 Guide to Writing AngularJS Directives

In this specific case, you should place the appropriate data on your controller's scope and share it with the directive via an attribute.

app.controller('SomeController', function($scope, locations) {
  locations().success(function(data) {
    $scope.locations = data;
  });
});

<ul class="list">
   <li ng-repeat="location in locations">
      <a href="#">{{location.id}}. {{location.name}}</a>
   </li>
</ul>
<map locations='locations'></map>

app.directive('map', function() {
  return {
    restrict: 'E',
    replace: true,
    template: '<div></div>',
    scope: {
      // creates a scope variable in your directive
      // called `locations` bound to whatever was passed
      // in via the `locations` attribute in the DOM
      locations: '=locations'
    },
    link: function(scope, element, attrs) {
      scope.$watch('locations', function(locations) {
        angular.forEach(locations, function(location, key) {
          // do something
        });
      });
    }
  };
});

In this way, the map directive can be used with any set of location data--the directive is not hard-coded to use a specific set of data, and simply linking the directive by including it in the DOM will not fire off random HTTP requests.

这篇关于在角度,如何通过JSON对象/数组指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆