Angular:如何在使用变量(字符串)来设置元素样式之前等待变量(字符串)?

时间:2017-12-21 17:01:11

标签: angular

我试图绘制两个由一条线连接的div(每个包含组件)。行的长度取决于div的宽度,我使用nativeElement属性访问它。

我使用ngAfterViewInit()来计算线条的宽度,使用div' nativeElements。但是,绘制div时没有任何连接它们的线。只有在我点击绘制线条的div之后才会这样做。

如何在更新线路长度之前等待lineWidth准备就绪?

这是模板:

<div class="bean-view" (click)="backgroundClick.emit()"> 
  <div class="bean-label-container" *ngIf="showLabels">
    <div class="bean-label" *ngFor="let label of bean.labels">{{label}}</div>
  </div>
  <div class="bean-icon-container" #beanIconContainerElement>
    <sb-bean-icon [type]="bean.type"></sb-bean-icon>
  </div>
  <div *ngIf="bean" class="bean" (click)="contentClick.emit()" #beanElement>
    <sb-bean-content [class.disable-click]="disableContentClick" [bean]="bean"></sb-bean-content>
  </div>
  <div class="bean-complete-marker completion-line" [style.width]="lineWidth"></div>
  <div class="bean-response-wrapper">
    <div class="bean-response" *ngFor="let response of bean.response" (click)="responseClick.emit()" #beanResponseElement>
      <sb-bean-content [bean]="response" [isResponse]="true"></sb-bean-content>
    </div>
  </div>
</div>

以下是组件代码:

import {
  Component,
  OnInit,
  ChangeDetectionStrategy,
  Input,
  Output,
  EventEmitter,
  ViewChild,
  ElementRef
} from '@angular/core';
import { Bean } from '../../../../shared/model';

@Component({
  selector: 'bean-view',
  templateUrl: './beanView.html',
  styleUrls: ['./beanView.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BeanViewComponent implements OnInit {
  @Input() bean: Bean;
  @Input() disableContentClick: Bean;
  @Input() showLabels: boolean;

  @Output() contentClick = new EventEmitter();
  @Output() responseClick = new EventEmitter();
  @Output() backgroundClick = new EventEmitter();

  @ViewChild('beanIconContainerElement') beanIconContainerElement;
  @ViewChild('beanElement') beanElement;
  @ViewChild('beanResponseElement') beanResponseElement;

  lineWidth: string = undefined;

  constructor() {
  }
  ngOnInit() {
  }
  ngAfterViewInit() {
    this.lineWidth = this.getWidth();
  }

  getWidth(): string {
    const bound: number = 200;
    const iconWidth: number = this.beanIconContainerElement.nativeElement.offsetWidth;
    const beanWidth: number = this.beanElement.nativeElement.offsetWidth;
    const width: number = bound - (iconWidth + beanWidth);
    return String(width) + 'px';
  }
}

2 个答案:

答案 0 :(得分:1)

使用ngStyle代替style.width

<div class="bean-complete-marker completion-line" [ngStyle]="{'width': lineWidth}"></div>

修改您的组件

import {
  Component,
  OnInit,
  ChangeDetectionStrategy,
  Input,
  Output,
  EventEmitter,
  ViewChild,
  ElementRef
} from '@angular/core';
import { Bean } from '../../../../shared/model';

@Component({
  selector: 'bean-view',
  templateUrl: './beanView.html',
  styleUrls: ['./beanView.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BeanViewComponent implements OnInit {
  @Input() bean: Bean;
  @Input() disableContentClick: Bean;
  @Input() showLabels: boolean;

  @Output() contentClick = new EventEmitter();
  @Output() responseClick = new EventEmitter();
  @Output() backgroundClick = new EventEmitter();

  @ViewChild('beanIconContainerElement') beanIconContainerElement;
  @ViewChild('beanElement') beanElement;
  @ViewChild('beanResponseElement') beanResponseElement;

  _lineWidth: string; // notice the change in variable

  get lineWidth() { return this._lineWidth; }

  set lineWidth(width: string) { this._lineWidth = width; } 

  constructor() {
  }
  ngOnInit() {
  }
  ngAfterViewInit() {
    this.lineWidth = this.getWidth();
  }

  getWidth(): string {
    const bound: number = 200;
    const iconWidth: number = this.beanIconContainerElement.nativeElement.offsetWidth;
    const beanWidth: number = this.beanElement.nativeElement.offsetWidth;
    const width: number = bound - (iconWidth + beanWidth);
    return String(width) + 'px';
  }
}

答案 1 :(得分:1)

您可以在样式指令中指定像素单位:

<div class="bean-complete-marker completion-line" [style.width.px]="lineWidth"></div>

在代码中,您可以删除ngAfterViewInitgetWidth,并将lineWidth定义为属性获取器:

public get lineWidth(): number {
    const isBeanIconReady: boolean = this.beanIconContainerElement && this.beanIconContainerElement.nativeElement;
    const isBeanElementReady: boolean = this.beanElement && this.beanElement.nativeElement;
    if (isBeanIconReady && isBeanElementReady) {
        const bound: number = 200;
        const iconWidth: number = this.beanIconContainerElement.nativeElement.offsetWidth;
        const beanWidth: number = this.beanElement.nativeElement.offsetWidth;
        const width: number = bound - (iconWidth + beanWidth);
        return width;
    } else {
        return 0;
    }
}

要确保DOM始终是最新的,请从组件声明中删除此行:

changeDetection: ChangeDetectionStrategy.OnPush