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>