Ответ 1
Как сказал Тобиас Босх
Переменная, объявленная внутри * 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);
});
}
Angular создается встроенный вид View_App_1
отдельно от View_App_0
. И наше выражение {{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