Как мы нацеливаемся на элементы, которые начинаются с ложного условия * ngIf? - PullRequest
1 голос
/ 25 февраля 2020

Мне нужно изменить атрибуты и / или стили элементов 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'" например.

1 Ответ

0 голосов
/ 25 февраля 2020

TemplateType должен быть инициализирован в ngOnInit, тогда вы можете получить ссылку на элементы dom, не пытайтесь изменить состояния любого элемента в методе ngAfterViewInit, и вам не нужно вызывать this.changeDetector.detectChanges();


ngOnInit(): void{ 
 this.TemplateType = this.determineElementType(); 
 if(this.ElementData.selfClosing){
      this.ForgedElement = this.buildElement();
      this.TemplateType = 'single element';
  }
}

ngAfterViewInit(): void{ this.initGraphic(); }

private initGraphic():void{
    if(!this.ElementData.selfClosing && this.TemplateType !== undefined){
          console.log(this.TemplateType);
          this.applyElementProperties();
     }else{ console.log('GRRRRRRRR!!!!!!!'); }    
 }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...