【问题标题】:Collection does not work if used inside ng-if, but work with ng-show如果在 ng-if 中使用,则集合不起作用,但与 ng-show 一起使用
【发布时间】:2017-09-08 20:33:41
【问题描述】:

我刚刚在我的应用程序中将 Angular 从 1.4.8 升级到 1.6.4,我遇到了从控制器变量获取数据的选择菜单的问题。

html:

<div id='main_app_header' ng-if="ctrl.shouldShowHeader">
  <accounts-directive></accounts-directive>
</div>

accounts 指令有选择菜单。

<div class="account-selector" ng-class="{'account-selector-disabled': haCtrl.accounts.length == 1}">
  <select id="account-select" ng-model="haCtrl.current"
      ng-options="account as account.name for account in haCtrl.accounts track by account.id"
      ng-change="haCtrl.changeAccount()"
      ng-disabled="haCtrl.accounts.length == 1">
  </select>
</div>

检查控制器时,所有数据都在那里。如果我将 ng-if 更改为 ng-show 一切正常。我不想使用 `ng-show 因为不想增加 DOM 中的观察者数量。我做错了什么吗?

指令代码:

"use strict";

(function() {

var AccountsDirective = function() {

return {

  restrict: 'E',

  replace: true,

  templateUrl: "app/components/header/account/view.html",

  controller: 'HeaderAccountCtrl as haCtrl'

};

};

  angular.module('mainNgApp').directive('AccountsDirective', AccountsDirective);

})();

控制器代码:

"use strict";

(function() {

var HeaderAccountCtrl = function(
$scope,
atomico,
events,
userState
) {

var _this = this;

atomico.ready(function() {
  _this.accounts = atomico.metadata['accounts'];
  _this.current  = atomico.metadata['account'];
});

_this.changeAccount = function(){
  atomico.metadata['account'] = _this.current;

  userState.setActiveAccountId(_this.current.id, function() {
    events.account.change(_this.current);
  });
};

};

HeaderAccountCtrl.$inject = [
'$scope',
'atomico',
'events',
'userState'
];

angular.module('mainNgApp').controller('HeaderAccountCtrl', HeaderAccountCtrl);

})();

切换到ng-if时遇到的错误如下:

TypeError: Cannot read property 'appendChild' of undefined
    at updateOptions (angular-1.6.4.self-cbf63df….js?body=1:30346)
    at Object.ngOptionsPostLink (angular-1.6.4.self-cbf63df….js?body=1:30249)
    at angular-1.6.4.self-cbf63df….js?body=1:1347
    at invokeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:10427)
    at nodeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:9816)
    at compositeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:9056)
    at nodeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:9810)
    at delayedNodeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:10177)
    at compositeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:9056)
    at compositeLinkFn (angular-1.6.4.self-cbf63df….js?body=1:9059) ""
TypeError: Cannot read property 'value' of undefined
    at SelectController.writeNgOptionsValue [as writeValue] (angular-1.6.4.self-cbf63df….js?body=1:30117)
    at Object.ngModelCtrl.$render (angular-1.6.4.self-cbf63df….js?body=1:32811)
    at ngModelWatch (angular-1.6.4.self-cbf63df….js?body=1:28960)
    at Scope.$digest (angular-1.6.4.self-cbf63df….js?body=1:17992)
    at Scope.$apply (angular-1.6.4.self-cbf63df….js?body=1:18270)
    at HTMLAnchorElement.<anonymous> (angular-1.6.4.self-cbf63df….js?body=1:27000)
    at HTMLAnchorElement.dispatch (jquery.self-bd7ddd3….js?body=1:5227)
    at HTMLAnchorElement.elemData.handle (jquery.self-bd7ddd3….js?body=1:4879)
TypeError: Cannot read property 'value' of undefined
    at SelectController.writeNgOptionsValue [as writeValue] (angular-1.6.4.self-cbf63df….js?body=1:30117)
    at Object.ngModelCtrl.$render (angular-1.6.4.self-cbf63df….js?body=1:32811)
    at angular-1.6.4.self-cbf63df….js?body=1:30156
    at Scope.$digest (angular-1.6.4.self-cbf63df….js?body=1:18000)
    at Scope.$apply (angular-1.6.4.self-cbf63df….js?body=1:18270)
    at HTMLAnchorElement.<anonymous> (angular-1.6.4.self-cbf63df….js?body=1:27000)
    at HTMLAnchorElement.dispatch (jquery.self-bd7ddd3….js?body=1:5227)
    at HTMLAnchorElement.elemData.handle (jquery.self-bd7ddd3….js?body=1:4879)
TypeError: Cannot read property 'nodeName' of undefined
    at nodeName_ (angular-1.6.4.self-cbf63df….js?body=1:886)
    at getBooleanAttrName (angular-1.6.4.self-cbf63df….js?body=1:3497)
    at Attributes.$set (angular-1.6.4.self-cbf63df….js?body=1:8650)
    at ngBooleanAttrWatchAction (angular-1.6.4.self-cbf63df….js?body=1:22801)
    at Scope.$digest (angular-1.6.4.self-cbf63df….js?body=1:18000)
    at Scope.$apply (angular-1.6.4.self-cbf63df….js?body=1:18270)
    at HTMLAnchorElement.<anonymous> (angular-1.6.4.self-cbf63df….js?body=1:27000)
    at HTMLAnchorElement.dispatch (jquery.self-bd7ddd3….js?body=1:5227)
    at HTMLAnchorElement.elemData.handle (jquery.self-bd7ddd3….js?body=1:4879)

【问题讨论】:

  • 假设关闭 div 不正确是帖子中的错字。你可以添加你的指令/组件定义吗?它可能会有所帮助。
  • 当然马特
  • HeaderAccountCtrl 的概要也很重要。这表明 accounts 属性尚未定义。你也可以列出来吗?
  • @MattTester 刚刚也添加了控制器。

标签: javascript angularjs


【解决方案1】:

错误提示accounts 未定义。查看您的控制器代码,这是通过 atomico.ready() 函数设置的,这就是问题所在。

ngShow 仅隐藏 DOM 中的元素,而ngIf 将添加和删除它们。

正在发生的事情是ngIf 正在将您的组件添加到 DOM 中,并且仅在此时实例化控制器。但是 atomico.ready() 没有被调用,因为(我假设)它在页面加载时已经被调用。

我不确定atomico service/factory 是什么,但我建议将参数传递给指令,而不是在指令中使用它。这样页面就可以处理atomico.ready() 回调,并在需要时将结果传递给指令。

所以,使用bindToController 参数:

var AccountsDirective = function() {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: "app/components/header/account/view.html",
        controller: 'HeaderAccountCtrl as haCtrl',
        scope: {},
        bindToController: {
             accounts: "<"
        }
    };
};

并使用:

<accounts-directive accounts="ctrl.accounts"></accounts-directive>

【讨论】:

  • Matt 我会尝试使用这个版本,如果它有效,我会接受正确的答案。谢谢。
  • 它仍然没有工作,将其移出 atomico.ready() 并使用绑定到控制器,仍然是同样的问题。不知道那里发生了什么。
猜你喜欢
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
  • 2018-02-27
  • 2016-10-29
  • 1970-01-01
  • 2015-06-29
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多