如何将模板引用变量与ngIf结合? [英] How do I combine a template reference variable with ngIf?

查看:84
本文介绍了如何将模板引用变量与ngIf结合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<div *ngIf="true" myHighlight #tRefVar="myHighlight"></div>
<div>tRefVar is {{tRefVar.foo}}</div>

即使*ngIf为true,我也得到一个Cannot read property 'foo' of undefined.如果删除*ngIf,它将正常工作!

我尝试使用Elvis运算符tRefVar?.foo,该运算符解决了该错误,但是从不使用该值更新.

https://plnkr.co/edit/5rsXygxK1sBbbkYdobjn?p=preview

我做错了什么?

解决方案

如Tobias Bosch所说

在* ngIf内部声明的变量不能在 * ngIf

https://github.com/angular/angular/issues/6179# issuecomment-233374700

只是相反的方式(即在* ngIf内声明一个变量并使用 它在* ngIf)之外无法正常工作,并且在设计上将无法正常工作.

https://github.com/angular/angular/issues/6179# issuecomment-233579605

为什么会这样?

1)不带* ngIf

让我们看看这个模板

<h2 myHighlight #tRefVar="myHighlight">tRefVar is {{tRefVar.foo}}</h2>
<div>tRefVar is {{tRefVar?.foo}}</div>

angular将为此创建以下viewDefinition:

function View_App_0(_l) {
  return jit_viewDef1(0,[(_l()(),jit_textDef2(null,['\n      '])),(_l()(),jit_elementDef3(0,
      null,null,2,'h2',[['myHighlight','']],null,null,null,null,null)),jit_directiveDef4(16384,
      [['tRefVar',4]],0,jit_HighlightDirective5,[jit_ElementRef6],null,null),(_l()(),
      jit_textDef2(null,['tRefVar is ',''])),(_l()(),jit_textDef2(null,['\n      '])),
      (_l()(),jit_elementDef3(0,null,null,1,'div',[],null,null,null,null,null)),(_l()(),
          jit_textDef2(null,['tRefVar is ',''])),(_l()(),jit_textDef2(null,['\n  ']))],
      null,function(_ck,_v) {
        var currVal_0 = jit_nodeValue7(_v,2).foo;
        _ck(_v,3,0,currVal_0);
        var currVal_1 = ((jit_nodeValue7(_v,2) == null)? null: jit_nodeValue7(_v,2).foo);
        _ck(_v,6,0,currVal_1);
      });
}

这里没有嵌入式视图.合而为一View_App_0.我们可以在这里看到我们的表达式{{tRefVar?.foo}}

var currVal_1 = ((jit_nodeValue7(_v,2) == null)? null: jit_nodeValue7(_v,2).foo);

它从索引为2的节点获取值

jit_directiveDef4(16384,
  [['tRefVar',4]],0,jit_HighlightDirective5,[jit_ElementRef6],null,null),(_l()(),
  jit_textDef2(null,['tRefVar is ','']))

在同一视图中声明的

2)使用* ngIf

然后让我们如下更改模板

<h2 *ngIf="true" myHighlight #tRefVar="myHighlight">tRefVar is {{tRefVar.foo}}</h2>
<div>tRefVar is {{tRefVar?.foo}}</div>

输出将是以下

function View_App_1(_l) {
  return jit_viewDef1(0,[(_l()(),jit_elementDef2(0,null,null,2,'h2',[['myHighlight',
      '']],null,null,null,null,null)),jit_directiveDef3(16384,[['tRefVar',4]],0,jit_HighlightDirective4,
      [jit_ElementRef5],null,null),(_l()(),jit_textDef6(null,['tRefVar is ','']))],
      null,function(_ck,_v) {
        var currVal_0 = jit_nodeValue7(_v,1).foo;
        _ck(_v,2,0,currVal_0);
      });
}
function View_App_0(_l) {
  return jit_viewDef1(0,[(_l()(),jit_textDef6(null,['\n'])),(_l()(),jit_anchorDef8(16777216,
      null,null,1,null,View_App_1)),jit_directiveDef3(16384,null,0,jit_NgIf9,[jit_ViewContainerRef10,
      jit_TemplateRef11],{ngIf:[0,'ngIf']},null),(_l()(),jit_textDef6(null,['\n'])),
      (_l()(),jit_elementDef2(0,null,null,1,'div',[],null,null,null,null,null)),(_l()(),
          jit_textDef6(null,['tRefVar is ',''])),(_l()(),jit_textDef6(null,['\n  ']))],
      function(_ck,_v) {
        var currVal_0 = true;
        _ck(_v,2,0,currVal_0);
      },function(_ck,_v) {
        var _co = _v.component;
        var currVal_1 = ((_co.tRefVar == null)? null: _co.tRefVar.foo);
        _ck(_v,5,0,currVal_1);
      });
}

View_App_0之外,Angular创建的嵌入式视图View_App_1.我们的表达式{{tRefVar?.foo}}变成了

var currVal_1 = ((_co.tRefVar == null)? null: _co.tRefVar.foo);

它刚刚成为组件属性,因为在View_App_0中没有节点将引用此模板变量.它已进入嵌入式视图View_App_1

var currVal_0 = jit_nodeValue7(_v,1).foo;

因此,我们无法引用已在嵌入式视图之外的嵌入式视图中声明的模板变量.

如何解决?

1)使用可见性标志,例如[hidden]或CSS类,而不是*ngIf

2)将表达式移到声明了tRefVar的嵌入式视图中

<ng-container *ngIf="true">
  <h2 myHighlight #tRefVar="myHighlight">tRefVar is {{tRefVar.foo}}</h2>
  <div>tRefVar is {{tRefVar?.foo}}</div>
</ng-container>

3)使用@ViewChild,因为它将代表组件属性.或使用@ViewChildren

<div *ngIf="true" myHighlight #tRefVar="myHighlight"></div>
<div>tRefVar is {{tRefVar.foo}}</div>

Even though the *ngIf is true, I get a Cannot read property 'foo' of undefined. If I remove the *ngIf, it works fine!

I tried using the Elvis operator tRefVar?.foo, which resolved the error, but then it never updates with the value.

https://plnkr.co/edit/5rsXygxK1sBbbkYdobjn?p=preview

What am I doing wrong?

解决方案

As Tobias Bosch said

A variable declared inside of an *ngIf cannot be used outside of the *ngIf

https://github.com/angular/angular/issues/6179#issuecomment-233374700

Only the opposite way (i.e. declare a variable inside of *ngIf and use it outside of *ngIf) is not working, and won't work by design.

https://github.com/angular/angular/issues/6179#issuecomment-233579605

Why is it so?

1) Without *ngIf

Let's see at this template

<h2 myHighlight #tRefVar="myHighlight">tRefVar is {{tRefVar.foo}}</h2>
<div>tRefVar is {{tRefVar?.foo}}</div>

angular will create the following viewDefinition for that:

function View_App_0(_l) {
  return jit_viewDef1(0,[(_l()(),jit_textDef2(null,['\n      '])),(_l()(),jit_elementDef3(0,
      null,null,2,'h2',[['myHighlight','']],null,null,null,null,null)),jit_directiveDef4(16384,
      [['tRefVar',4]],0,jit_HighlightDirective5,[jit_ElementRef6],null,null),(_l()(),
      jit_textDef2(null,['tRefVar is ',''])),(_l()(),jit_textDef2(null,['\n      '])),
      (_l()(),jit_elementDef3(0,null,null,1,'div',[],null,null,null,null,null)),(_l()(),
          jit_textDef2(null,['tRefVar is ',''])),(_l()(),jit_textDef2(null,['\n  ']))],
      null,function(_ck,_v) {
        var currVal_0 = jit_nodeValue7(_v,2).foo;
        _ck(_v,3,0,currVal_0);
        var currVal_1 = ((jit_nodeValue7(_v,2) == null)? null: jit_nodeValue7(_v,2).foo);
        _ck(_v,6,0,currVal_1);
      });
}

there is no embedded view here. All in one View_App_0. And we can see here our expression {{tRefVar?.foo}}

var currVal_1 = ((jit_nodeValue7(_v,2) == null)? null: jit_nodeValue7(_v,2).foo);

it takes value from node with index 2

jit_directiveDef4(16384,
  [['tRefVar',4]],0,jit_HighlightDirective5,[jit_ElementRef6],null,null),(_l()(),
  jit_textDef2(null,['tRefVar is ','']))

that declared in the same view

2) With *ngIf

Then let's change template as follows

<h2 *ngIf="true" myHighlight #tRefVar="myHighlight">tRefVar is {{tRefVar.foo}}</h2>
<div>tRefVar is {{tRefVar?.foo}}</div>

The output will be the following

function View_App_1(_l) {
  return jit_viewDef1(0,[(_l()(),jit_elementDef2(0,null,null,2,'h2',[['myHighlight',
      '']],null,null,null,null,null)),jit_directiveDef3(16384,[['tRefVar',4]],0,jit_HighlightDirective4,
      [jit_ElementRef5],null,null),(_l()(),jit_textDef6(null,['tRefVar is ','']))],
      null,function(_ck,_v) {
        var currVal_0 = jit_nodeValue7(_v,1).foo;
        _ck(_v,2,0,currVal_0);
      });
}
function View_App_0(_l) {
  return jit_viewDef1(0,[(_l()(),jit_textDef6(null,['\n'])),(_l()(),jit_anchorDef8(16777216,
      null,null,1,null,View_App_1)),jit_directiveDef3(16384,null,0,jit_NgIf9,[jit_ViewContainerRef10,
      jit_TemplateRef11],{ngIf:[0,'ngIf']},null),(_l()(),jit_textDef6(null,['\n'])),
      (_l()(),jit_elementDef2(0,null,null,1,'div',[],null,null,null,null,null)),(_l()(),
          jit_textDef6(null,['tRefVar is ',''])),(_l()(),jit_textDef6(null,['\n  ']))],
      function(_ck,_v) {
        var currVal_0 = true;
        _ck(_v,2,0,currVal_0);
      },function(_ck,_v) {
        var _co = _v.component;
        var currVal_1 = ((_co.tRefVar == null)? null: _co.tRefVar.foo);
        _ck(_v,5,0,currVal_1);
      });
}

Angular created embedded view View_App_1 apart to View_App_0 . And our expression {{tRefVar?.foo}} has turned into

var currVal_1 = ((_co.tRefVar == null)? null: _co.tRefVar.foo);

it just becames component property because there is no node that will reference to this template variable in View_App_0. It's gone to embedded view View_App_1

var currVal_0 = jit_nodeValue7(_v,1).foo;

So we cannot refer to template variable that has been declared in embedded view outside of embedded view.

How to solve it?

1) Use visibility flag like [hidden] or css class instead of *ngIf

2) Move your expression inside embedded view where tRefVar is declared

<ng-container *ngIf="true">
  <h2 myHighlight #tRefVar="myHighlight">tRefVar is {{tRefVar.foo}}</h2>
  <div>tRefVar is {{tRefVar?.foo}}</div>
</ng-container>

3) Use @ViewChild because it will represent component property. Or use @ViewChildren

这篇关于如何将模板引用变量与ngIf结合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆