简体   繁体   English

如果在ng-if中使用,则集合不起作用,但与ng-show一起使用

[英]Collection does not work if used inside ng-if, but work with ng-show

I just upgraded Angular from 1.4.8 to 1.6.4 in my application and I am facing an issue with a select menu that gets the data from a controller variable. 我刚刚在我的应用程序中将Angular从1.4.8升级到1.6.4,我遇到了一个选择菜单的问题,该菜单从控制器变量中获取数据。

html: HTML:

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

The accounts directive has the select menu. 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>

When inspecting controllers all data is there. 检查控制器时,所有数据都在那里。 If i change the ng-if to ng-show everything works fine. 如果我改变ng-ifng-show一切正常。 I do not want to use `ng-show as not wanted to increase the number of watchers in the DOM. 我不想使用`ng-show,因为不想增加DOM中观察者的数量。 Is there something wrong I am doing? 我在做什么不对劲?

Directive Code: 指令代码:

"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);

})();

Controller Code: 控制器代码:

"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);

})();

The errors i get when switching to ng-if are as below: 切换到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)

The error is suggesting that accounts is not defined. 该错误表明未定义accounts Looking at your controller code, this is set via the atomico.ready() function which is where the problem is going to be. 查看控制器代码,这是通过atomico.ready()函数设置的,这是问题所在。

ngShow only hides elements in the DOM whereas ngIf will add and remove them. ngShow只隐藏DOM中的元素,而ngIf将添加和删除它们。

What is happening is that the ngIf is adding your component into the DOM, and it is only at this point that the controller is instantiated. 发生的事情是ngIf正在将您的组件添加到DOM中,并且仅在此时控制器被实例化。 However the atomico.ready() is not being called because (I assume) it has already been called when the page was loaded. 然而, atomico.ready()没有被调用,因为(我假设)它已经在页面加载时被调用。

I'm not sure what the atomico service/factory is, but I'd suggest passing arguments to the directive instead of using it in the directive. 我不确定atomico服务/工厂是什么,但我建议将参数传递给指令而不是在指令中使用它。 That way the page can handle the atomico.ready() callback instead, and pass the results to the directive when needed. 这样页面就可以处理atomico.ready()回调,并在需要时将结果传递给指令。

So, make use of the bindToController parameter: 因此,请使用bindToController参数:

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

And pass in using: 并传递使用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM