【问题标题】:angular directive - correlative requests角度指令 - 相关请求
【发布时间】:2012-10-31 17:17:30
【问题描述】:

我为以下小部件属性创建了一个自定义指令:

<div widget></div>

基本上,该指令只是创建一些模板代码并将 html 放入 widget-tag 中。 这是指令:

skdApp.directive("widget", function() {
  return {
    restrict: 'A',
    template: htmlTemplate,
    link: function($scope, element, attri) {
      /*
       * setup event handler and twitter bootstrap components here
       */
    }
  }

htmlTemplate 是基本的 html 代码,它也使用自定义指令(例如 &lt;seal&gt; 标签):

var htmlTemplate = '<div ng-controller="OfferCtrl">' +
                     '<div class="container">' +
                       <seal></seal>' +
                       '...'+
                     '</div>' +
                   '</div>';

在我的控制器中,我首先请求在

中显示一些数据。 我有一个“提供”服务,它封装了从服务器请求数据的所有逻辑。我使用的方法称为 Offer.query()。
skdApp.controller('OfferCtrl', function OfferCtrl ($scope, Offer) {
  var o = Offer.query({id: 1}, function (response) {
    $scope.offer = response;
  });
});

在响应处理程序中,我将结果绑定到范围。 我现在面临的问题是该指令也请求数据,但此请求取决于从 Offer.query() 接收到的数据。 IE。 Offer.query() 的响应返回一个 ID(我们称之为 myID),这是 seal 指令请求更多数据所必需的。 因此,我只是将我所有的逻辑都放在了回调 Offer.query 回调函数中。这似乎不是最好的方法。

所以我想把这部分移到&lt;seal&gt;指令的链接函数中:

skdApp.directive("seal", function() {

  var sealHTML = '<div>{{offer.data.foobar}}</div>';

  return {
    restrict: 'E',
    template: sealHTML,
    link: function($scope, element, attrs) {

      $scope.$watch('offer.myId', function (newValue, oldValue) {

       if (typeof newValue !== "undefined") {

         /* request more data with myId 
          * and bind the result to offer.data
          */    

       }

      });

    }
});

这种方法是否符合“角度”,或者是否有其他更好的方法(在结构方面)可以在角度上做到这一点?

【问题讨论】:

  • 你将你的服务器交互封装到一个服务中,你的控制器很好而且“瘦”,你的指令 $watch()es 用于 $scope 更改以触发一些操作。我喜欢它。

标签: javascript angularjs directive


【解决方案1】:

您可以在 child 指令中查看 offer.myId,因为 parent(widget) 和 child(seal) 共享相同的范围。默认情况下,指令不会创建新范围。

我认为您广播自定义事件以通知子指令并在需要时隔离范围以避免范围破坏。

http://docs.angularjs.org/api/ng.$rootScope.Scope

【讨论】:

    【解决方案2】:

    我将采用这种 Reverse-Jeopardy 风格(以答案的形式提出问题)。我一直在考虑解决我最近看到的这个问题。它显然有效,但它有一些行为特征,我最初很想将其标记为“错误”。经过深入思考,我意识到这些特征在某些非常具体的场景中可能是可取的

    我当然不会把它作为一个通用的解决方案,每次遇到需要绑定异步返回的数据时使用。我提出它是为了强调这样一个事实,即这种情况提出的问题有多个可能的答案。在某些情况下,可能存在真正的业务逻辑需要阻止 UI 呈现,直到服务调用返回。在其他情况下,让 UI 保持活跃并响应不相关的工作可能更合适。

    例如,在订单处理系统的情况下,我可能非常希望阻止客户端线程与视图元素交互,直到知道销售交易的结果。对于具有服务器端公式计算的基于 Web 的电子表格应用程序,情况并非如此。

    我认为满足这一需求的异步和同步模式可以共存是一件很棒的事情。也就是说,返回一个 Promise 对象并不会强制客户端使用它,就像将返回值放在一个范围内会强制客户端观察它们一样。

    以下演示了一种处理此要求的方法同步以及之前探索的异步watch( ) 样式。:

    var servicesModule = servicesModule || angular.module('myModule', []);
    
    servicesModule.factory('thingClient', 
        ['$http', '$q', function( $http, $q ) {
            return new ThingClient($http, $q);
        }]
    );
    
    function ThingClient($http, $q) {
        function callService(scopeObject) {
            var defer = $q.defer();
            var promise = defer.promise;
            $http({
                method: 'POST',
                url: 'http://at/some/url/',
                data: { x: 'y', y: 'z', z: 'x', one: 1, two: 2, three: 3},
                cache: false
            }, function(data) {
                scopeObject.data = data;
                defer.resolve(data);
            }, function() {
                scopeObject.data = null;
                defer.resolve(null)
            });
    
            return promise;
        }
    }
    

    client-service.js

    function ConsumingController( $scope, thingClient ) {
        // Be careful to use an object (so you have data wrapped such that it
        // is eligible for prototypical inheritance and call by reference without
        // passing the scope itself).  Leave the 'data' element undefined so you
        // can trigger the transition from undefined -> null in the failure case
        // and not just the on-success case. 
        $scope.dto = { data: undefined };
        var promise = thingClient.callService(scope.dto);
    
        // Asynchronous strategy
        $scope.$watch('offer.myId', function (newValue, oldValue) {
            if( newValue == null ) {
                // Fail!
            } else {
                // Succeed!
            }
        }
    
        // Synchronous strategy
        if( promise.then( 
            function(data) { 
                if( data == null ) { 
                    // Fail
                } else {
                    // Succeed
                }
            }
        }
    }
    

    消费控制器.js

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 1970-01-01
      • 2016-05-05
      • 2016-09-19
      • 2015-03-15
      • 2018-04-25
      相关资源
      最近更新 更多