如何在 Angular 1.5 组件中等待绑定(没有 $scope.$watch)
How to wait for binding in Angular 1.5 component (without $scope.$watch)
我正在编写一个 Angular 1.5 指令,我 运行 遇到了一个令人讨厌的问题,试图在绑定数据存在之前对其进行操作。
这是我的代码:
app.component('formSelector', {
bindings: {
forms: '='
},
controller: function(FormSvc) {
var ctrl = this
this.favorites = []
FormSvc.GetFavorites()
.then(function(results) {
ctrl.favorites = results
for (var i = 0; i < ctrl.favorites.length; i++) {
for (var j = 0; j < ctrl.forms.length; j++) {
if (ctrl.favorites[i].id == ctrl.newForms[j].id) ctrl.forms[j].favorite = true
}
}
})
}
...
如您所见,我正在调用 AJAX 来获取收藏夹,然后根据我绑定的表单列表进行检查。
问题是,甚至在填充绑定之前就已经实现了诺言...所以当我 运行 循环时,ctrl.forms 仍然是未定义的!
不使用 $scope.$watch(这是 1.5 组件的一部分)我如何等待绑定完成?
您可以使用新的生命周期挂钩,特别是$onChanges
, to detect the first change of a binding by calling the isFirstChange
method. Read more about this here。
这是一个例子:
<div ng-app="app" ng-controller="MyCtrl as $ctrl">
<my-component binding="$ctrl.binding"></my-component>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js"></script>
<script>
angular
.module('app', [])
.controller('MyCtrl', function($timeout) {
$timeout(() => {
this.binding = 'first value';
}, 750);
$timeout(() => {
this.binding = 'second value';
}, 1500);
})
.component('myComponent', {
bindings: {
binding: '<'
},
controller: function() {
// Use es6 destructuring to extract exactly what we need
this.$onChanges = function({binding}) {
if (angular.isDefined(binding)) {
console.log({
currentValue: binding.currentValue,
isFirstChange: binding.isFirstChange()
});
}
}
}
});
</script>
我有一个类似的问题,我这样做是为了避免在我要发送的值准备好之前调用组件:
<form-selector ng-if="asyncValue" forms="asyncValue" ></form-selector>
我遇到了类似的问题,我发现这篇文章很有帮助。
http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html
我有一个 ajax 调用在页面加载时命中服务器,我的组件需要 ajax return 值才能正确加载。我是这样实现的:
this.$onChanges = function (newObj) {
if (newObj.returnValFromAJAX)
this.returnValFromAJAX = newObj.returnValFromAJAX;
};
现在我的组件可以完美运行了。作为参考,我使用 Angular 1.5.6
楼主说:
the promise is being fulfilled even before the binding is populated...
sot hat by the time I run the loop, ctrl.forms is still undefined
自从 AngularJS 1.5.3 以来,我们有了 lifecycle hooks 并且为了满足 OP 的问题,您只需要移动取决于 [=11= 中满足的绑定的代码]:
$onInit() - Called on each controller after all the controllers on an
element have been constructed and had their bindings initialized (and
before the pre & post linking functions for the directives on this
element). This is a good place to put initialization code for your
controller.
因此在示例中:
app.component('formSelector', {
bindings: {
forms: '='
},
controller: function(FormSvc) {
var ctrl = this;
this.favorites = [];
this.$onInit = function() {
// At this point, bindings have been resolved.
FormSvc
.GetFavorites()
.then(function(results) {
ctrl.favorites = results;
for (var i = 0; i < ctrl.favorites.length; i++) {
for (var j = 0; j < ctrl.forms.length; j++) {
if (ctrl.favorites[i].id == ctrl.newForms[j].id) {
ctrl.forms[j].favorite = true;
}
}
}
});
}
}
所以是的,有一个 $onChanges(changesObj)
,但是 $onInit()
专门解决了最初的问题,即我们什么时候可以保证绑定已经解决。
我正在编写一个 Angular 1.5 指令,我 运行 遇到了一个令人讨厌的问题,试图在绑定数据存在之前对其进行操作。
这是我的代码:
app.component('formSelector', {
bindings: {
forms: '='
},
controller: function(FormSvc) {
var ctrl = this
this.favorites = []
FormSvc.GetFavorites()
.then(function(results) {
ctrl.favorites = results
for (var i = 0; i < ctrl.favorites.length; i++) {
for (var j = 0; j < ctrl.forms.length; j++) {
if (ctrl.favorites[i].id == ctrl.newForms[j].id) ctrl.forms[j].favorite = true
}
}
})
}
...
如您所见,我正在调用 AJAX 来获取收藏夹,然后根据我绑定的表单列表进行检查。
问题是,甚至在填充绑定之前就已经实现了诺言...所以当我 运行 循环时,ctrl.forms 仍然是未定义的!
不使用 $scope.$watch(这是 1.5 组件的一部分)我如何等待绑定完成?
您可以使用新的生命周期挂钩,特别是$onChanges
, to detect the first change of a binding by calling the isFirstChange
method. Read more about this here。
这是一个例子:
<div ng-app="app" ng-controller="MyCtrl as $ctrl">
<my-component binding="$ctrl.binding"></my-component>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js"></script>
<script>
angular
.module('app', [])
.controller('MyCtrl', function($timeout) {
$timeout(() => {
this.binding = 'first value';
}, 750);
$timeout(() => {
this.binding = 'second value';
}, 1500);
})
.component('myComponent', {
bindings: {
binding: '<'
},
controller: function() {
// Use es6 destructuring to extract exactly what we need
this.$onChanges = function({binding}) {
if (angular.isDefined(binding)) {
console.log({
currentValue: binding.currentValue,
isFirstChange: binding.isFirstChange()
});
}
}
}
});
</script>
我有一个类似的问题,我这样做是为了避免在我要发送的值准备好之前调用组件:
<form-selector ng-if="asyncValue" forms="asyncValue" ></form-selector>
我遇到了类似的问题,我发现这篇文章很有帮助。 http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html
我有一个 ajax 调用在页面加载时命中服务器,我的组件需要 ajax return 值才能正确加载。我是这样实现的:
this.$onChanges = function (newObj) {
if (newObj.returnValFromAJAX)
this.returnValFromAJAX = newObj.returnValFromAJAX;
};
现在我的组件可以完美运行了。作为参考,我使用 Angular 1.5.6
楼主说:
the promise is being fulfilled even before the binding is populated... sot hat by the time I run the loop, ctrl.forms is still undefined
自从 AngularJS 1.5.3 以来,我们有了 lifecycle hooks 并且为了满足 OP 的问题,您只需要移动取决于 [=11= 中满足的绑定的代码]:
$onInit() - Called on each controller after all the controllers on an element have been constructed and had their bindings initialized (and before the pre & post linking functions for the directives on this element). This is a good place to put initialization code for your controller.
因此在示例中:
app.component('formSelector', {
bindings: {
forms: '='
},
controller: function(FormSvc) {
var ctrl = this;
this.favorites = [];
this.$onInit = function() {
// At this point, bindings have been resolved.
FormSvc
.GetFavorites()
.then(function(results) {
ctrl.favorites = results;
for (var i = 0; i < ctrl.favorites.length; i++) {
for (var j = 0; j < ctrl.forms.length; j++) {
if (ctrl.favorites[i].id == ctrl.newForms[j].id) {
ctrl.forms[j].favorite = true;
}
}
}
});
}
}
所以是的,有一个 $onChanges(changesObj)
,但是 $onInit()
专门解决了最初的问题,即我们什么时候可以保证绑定已经解决。