Мне нужно изменить атрибуты и / или стили элементов dom, которых нет, пока условие *ngIf
не вернет true, к которому я пытаюсь получить доступ с помощью декоратора @viewChild()
. Пока что независимо от того, что я пытаюсь сделать, я получаю сообщение об ошибке:
Невозможно прочитать свойство nativeElement из неопределенного
Я натолкнулся на несколько ресурсов, в которых говорится, что мы должны применить ChangeDetectorRef
так что мы можем обновить компонент вручную после установки переменной, которая переключает элемент dom, однако мне тоже не повезло с этим методом. Примеры, с которыми я сталкивался, даже не используют {static: true}
в их * Декораторы 1011 *, поэтому я подумал, что, возможно, были внесены другие изменения, которые требуют изменения того, как нам нужно go применить это решение, или, может быть, теперь существует другой поощряемый стандарт.
Мой код в настоящее время выглядит так:
внутри компонента
//Where my data enter the component.
@Input() ElementData : OvaadGraphicObject;
TemplateType: string; //this variable toggles the *ngIf conditions
@ViewChild('graphicContainer', {static: true}) GraphicContainer: ElementRef;
//setting the TemplateType variable when the component initializes
ngOnInit(): void{ this.TemplateType = this.determineElementType(); }
//attempts to effect dom element after *ngIf condition is true and element exists
ngAfterViewInit(): void{ this.initGraphic(); }
/*I was initially setting the TemplateType var here and decided to split it apart to
set things in different lifecycles to force it to work in the proper order.*/
private initGraphic():void{
if(this.ElementData.selfClosing){
this.ForgedElement = this.buildElement();
this.TemplateType = 'single element';
}
else{
//this.TemplateType = this.determineElementType();
this.changeDetector.detectChanges();//
/*this checks to make sure the var isn't undefined before attempting to access the dom element
which from the console.log provides the correct result*/
if(this.TemplateType !== undefined){
console.log(this.TemplateType);
this.applyElementProperties();//this is what attempts to modify the dom element
}
else{ console.log('GRRRRRRRR!!!!!!!'); }
}
}
private applyElementProperties():void{
const attributes: OvaadGraphicAttribute[] = this.ElementData.attributes;
const styles: OvaadSvgStyleProperty[] = this.ElementData.styles;
if(attributes.length > 0){
attributes.forEach(a=>{
//GraphicContainer is somehow still undefined at this point causing an error
this.GraphicContainer.nativeElement.setAttribute(a.attribute, a.setting);
});
}
if(styles.length > 0){
styles.forEach(a=>{
this.GraphicContainer.nativeElement.style[a.property] = a.setting;
});
}
}
внутри моего шаблона
<svg:g *ngIf="TemplateType === 'single element'" [innerHtml]='insertElement()'></svg:g>
<svg:g #graphicContainer *ngIf="TemplateType == 'group element'">
<svg:g svg-component *ngFor="let item of ElementData.subElements" [ElementData]="item"></svg:g>
</svg:g>
<svg:linearGradient #graphicContainer *ngIf="TemplateType === 'linear gradient'">
<svg:g svg-component *ngFor="let item of ElementData.subElements" [ElementData]="item"></svg:g>
</svg:linearGradient>
<svg:radialGradient #graphicContainer *ngIf="TemplateType === 'radial gradient'">
<svg:g svg-component *ngFor="let item of ElementData.subElements" [ElementData]="item"></svg:g>
</svg:radialGradient>
<svg:symbol #graphicContainer *ngIf="TemplateType === 'linear gradient'">
<svg:g svg-component *ngFor="let item of ElementData.subElements" [ElementData]="item"></svg:g>
</svg:symbol>
Как вы видите в моем шаблоне, я использую #graphicContainer
для каждого элемента, кроме минус первого. Я подумал, что из-за того, как работает *ngIf
, в домах не будет никакой путаницы, потому что всегда будет только один из них. Я удалил #graphicContainer
из всех, кроме одного, чтобы посмотреть, не вызывают ли они какой-то путаницы, но поведение осталось прежним. Как мне заставить это работать?
Обновление
Чтобы помочь лучше понять, что происходит, вот как выглядит функция determineElementType()
.
private determineElementType():string{
const item: string = this.ElementData.element;
let elementType: string;
if(item === 'g'){ elementType = 'group element'; }
else if(item === 'linearGradient'){ elementType = 'linear gradient'; }
else if(item === 'radialGradient'){ elementType = 'radial gradient'; }
else if(item === 'symbol'){ elementType = 'symbol'; }
else{ elementType = 'unknown element'; }
return elementType as string;
}
Я мог бы установить условие *ngIf
так, чтобы оно работало непосредственно с основным объектом данных, который проходит через @Input()
, но эта функциональность не понадобится в каждом случае использования. В тех случаях, когда это происходит, перед переключением элемента необходимо выполнить другие действия, в противном случае могут возникнуть другие ошибки из-за того, что не существует других элементов, которые, в свою очередь, будут отображаться в элементе, поэтому я делаю это так, а не просто *ngIf="ElementData.element === 'g'"
например.