javascript - can't simply use ES6 promise to update data in ng-repeat? -
i'm trying build drill-down list angular , es6 promise. without using promise code works demoed in snippet below. every time click parent, expands children (just foo , bar in sample 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 change using promise, goes wrong: you'd have double click element expand , scopes messed up.
the difference in load
function in service , directive controller. far haven't looked angular's $q
api why can't use promise? there 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 require es6 promises either expose hook setting scheduler (like bluebird promises) or expose "post-then" hooks - neither of publicly.
you'd have coerce es6 promise $q
1 doing:
$q.when(datasvc.load()).then(...
alternatively, can write helper binding scope:
var withdigest = function(fn){ fn().then(function(){ $rootscope.evalasync(angular.noop); // schedule digest if not scheduled }); };
and do:
withdigest(function(){ return datasvc.load().then(... });
Comments
Post a Comment