不能简单地用ES6承诺更新在NG-重复数据?简单、数据、NG

2023-09-13 04:16:10 作者:心情好于坏,看的是女人。

我试图建立与角度和ES6承诺下钻列表。如果不使用答应我​​的code ++工程,如下面的代码片段演示了。您单击父时,它都会扩大了孩子们(只是foo和样本为简单起见巴)。

\r\r

angular.module('示范',[])\r  .controller('DemoController',['$范围,DataService的',函数($范围,dataSvc){\r    $ scope.entities = dataSvc.loadInitialData();\r  }])\r  .directive('钻取',['$编译,DataService的',函数($编译,dataSvc){\r    返回{\r      限制:'A',\r      范围: {\r        实体:'='\r      },\r      控制器:函数($范围){\r        $ scope.load =功能(){\r          this.entity.subEntities = dataSvc.load();\r        };\r      },\r      编译:函数(元素){\r        VAR内容= element.contents()remove()方法。\r        VAR编译= NULL;\r\r        返回功能(范围,元素){\r          如果(!编译){\r            编译= $编译(内容);\r          }\r\r          编译(范围,功能(克隆){\r            element.append(克隆);\r          });\r        };\r      },\r      模板:\r        '<李NG重复=实体的实体>' +\r          '&所述; A HREF =#纳克点击=负载()>&下;跨度纳克绑定=entity.name>&下; /跨度>&下; / A>' +\r          '< UL向下钻取实体=entity.subEntities>< / UL>' +\r        '< /李>'\r    };\r  }])\r  。服务('的DataService',函数(){\r    this.loadInitialData =功能(){\r      返回[\r        {\r          名称:'富',\r          subEntities:[]\r        },\r        {\r          名称:'棒',\r          subEntities:[]\r        }\r      ];\r    };\r    this.load =功能(){\r      返回this.loadInitialData();\r    };\r  });

\r

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/angular.js/1.3.0/angular.min.js\"></script>\r&LT; D​​IV NG-应用=演示NG-控制器=DemoController&GT;\r  &LT; UL向下钻取实体=实体&GT;&LT; / UL&GT;\r&LT; / DIV&GT;

\r\r\r

然而,当我将其更改为使用的承诺,不顺心的事:现在你必须双击该元素将其展开和范围也搞砸了。

的区别是本质上的服务和指令控制器只是在负荷功能。到目前为止,我还没有真正看着角的 $ Q API,但为什么我不能只使用承诺?有一些神奇的还有在 $ Q

\r\r

angular.module('示范',[])\r  .controller('DemoController',['$范围,DataService的',函数($范围,dataSvc){\r    $ scope.entities = dataSvc.loadInitialData();\r  }])\r  .directive('钻取',['$编译,DataService的',函数($编译,dataSvc){\r    返回{\r      限制:'A',\r      范围: {\r        实体:'='\r      },\r      控制器:函数($范围){\r        $ scope.load =功能(){\r          变种S =这一点;\r          dataSvc.load()。然后(功能(RES){\r            s.entity.subEntities =资源;\r          });\r        };\r      },\r      编译:函数(元素){\r        VAR内容= element.contents()remove()方法。\r        VAR编译= NULL;\r\r        返回功能(范围,元素){\r          如果(!编译){\r            编译= $编译(内容);\r          }\r\r          编译(范围,功能(克隆){\r            element.append(克隆);\r          });\r        };\r      },\r      模板:\r        '&LT;李NG重复=实体的实体&GT;' +\r          '&所述; A HREF =#纳克点击=负载()&GT;&下;跨度纳克绑定=entity.name&GT;&下; /跨度&GT;&下; / A&GT;' +\r          '&LT; UL向下钻取实体=entity.subEntities&GT;&LT; / UL&GT;' +\r        '&LT; /李&GT;'\r    };\r  }])\r  。服务('的DataService',函数(){\r    this.loadInitialData =功能(){\r      返回[\r          {\r            名称:'富',\r            subEntities:[]\r          },\r          {\r            名称:'棒',\r            subEntities:[]\r          }\r        ];\r    };\r    this.load =功能(){\r      返回新希望(函数(解析,拒绝){\r        解决([\r          {\r            名称:'富',\r            subEntities:[]\r          },\r          {\r            名称:'棒',\r            subEntities:[]\r          }\r        ]);\r      });\r    };\r  }); 都说公路货运市场不景气,上半年这两个细分领域的货量却显著增长

\r

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/angular.js/1.3.0/angular.min.js\"></script>\r&LT; D​​IV NG-应用=演示NG-控制器=DemoController&GT;\r  &LT; UL向下钻取实体=实体&GT;&LT; / UL&GT;\r&LT; / DIV&GT;

\r\r\r

解决方案

这将需要ES6承诺,无论是揭露一个钩子设置调度程序(如青鸟承诺),或揭露,那么后挂钩 - 两者都不是不公开。

您不得不要挟ES6承诺到 $ Q 一个接这样做的:

  $ q.when(dataSvc.load()),然后(... 

另外,你可以写一个帮手绑定到一个范围:

  VAR withDigest =功能(FN){    FN()。然后(函数(){        $ rootScope.evalAsync(angular.noop); //时间表摘要,如果没有安排    });}; 

然后执行:

  withDigest(函数(){    返回dataSvc.load()。然后(...}); 

I'm trying to build a drill-down list with angular and es6 promise. Without using promise my code works as demoed in the snippet below. Every time you click the parent, it expands the children (just foo and bar in the sample for simplicity).

angular.module('demo', [])
  .controller('DemoController', ['$scope', 'dataService', function($scope, dataSvc) {
    $scope.entities = dataSvc.loadInitialData();
  }])
  .directive('drillDown', ['$compile', 'dataService', function($compile, dataSvc) {
    return {
      restrict: 'A',
      scope: {
        entities: '='
      },
      controller: function($scope) {
        $scope.load = function() {
          this.entity.subEntities = dataSvc.load();
        };
      },
      compile: function(element) {
        var contents = element.contents().remove();
        var compiled = null;

        return function(scope, element) {
          if (!compiled) {
            compiled = $compile(contents);
          }

          compiled(scope, function(clone) {
            element.append(clone);
          });
        };
      },
      template:
        '<li ng-repeat="entity in entities">' +
          '<a href="#" ng-click="load()"><span ng-bind="entity.name"></span></a>' +
          '<ul drill-down entities="entity.subEntities"></ul>' +
        '</li>'
    };
  }])
  .service('dataService', function() {
    this.loadInitialData = function() {
      return [
        {
          name: 'foo',
          subEntities: []
        },
        {
          name: 'bar',
          subEntities: []
        }
      ];
    };
    this.load = function() {
      return this.loadInitialData();
    };
  });

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
  <ul drill-down entities="entities"></ul>
</div>

However when I change it to using promise, something goes wrong: now you'd have to double click the element to expand it and the scopes are also messed up.

The difference is essentially just in the load function in the service and the directive controller. So far I haven't really looked into angular's $q api but why can't I just use promise? Is there some magic there in $q?

angular.module('demo', [])
  .controller('DemoController', ['$scope', 'dataService', function($scope, dataSvc) {
    $scope.entities = dataSvc.loadInitialData();
  }])
  .directive('drillDown', ['$compile', 'dataService', function($compile, dataSvc) {
    return {
      restrict: 'A',
      scope: {
        entities: '='
      },
      controller: function($scope) {
        $scope.load = function() {
          var s = this;
          dataSvc.load().then(function(res) {
            s.entity.subEntities = res;
          });
        };
      },
      compile: function(element) {
        var contents = element.contents().remove();
        var compiled = null;

        return function(scope, element) {
          if (!compiled) {
            compiled = $compile(contents);
          }

          compiled(scope, function(clone) {
            element.append(clone);
          });
        };
      },
      template:
        '<li ng-repeat="entity in entities">' +
          '<a href="#" ng-click="load()"><span ng-bind="entity.name"></span></a>' +
          '<ul drill-down entities="entity.subEntities"></ul>' +
        '</li>'
    };
  }])
  .service('dataService', function() {
    this.loadInitialData = function() {
      return [
          {
            name: 'foo',
            subEntities: []
          },
          {
            name: 'bar',
            subEntities: []
          }
        ];
    };
    this.load = function() {
      return new Promise(function(resolve, reject) {
        resolve([
          {
            name: 'foo',
            subEntities: []
          },
          {
            name: 'bar',
            subEntities: []
          }
        ]);
      });
    };
  });

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoController">
  <ul drill-down entities="entities"></ul>
</div>

解决方案

This would require ES6 promises to either expose a hook for setting the scheduler (like bluebird promises) or to expose "post-then" hooks - neither of which it does publicly.

You'd have to coerce the ES6 promise to a $q one by doing:

$q.when(dataSvc.load()).then(...

Alternatively, you can write a helper for binding it to a scope:

var withDigest = function(fn){
    fn().then(function(){
        $rootScope.evalAsync(angular.noop); // schedule digest if not scheduled
    });
};

And then do:

withDigest(function(){
    return dataSvc.load().then(...
});