连接后动态更改Angular材质叠加位置

时间:2019-01-17 16:23:47

标签: angular angular-material overlay angular-material2 angular-cdk

window-resize事件之后,有许多需要重新放置的叠加层。

当前初始配置的PositionStrategy 具有依赖于外部变量的逻辑以类似于CSS Grid / Flexbox行为对齐Overaly。

这个material2 github issue似乎只能使用OverlayRef.dispose() => OverlayRef.create()

是否有符合以下条件的解决方案:

  • 可以使用非静态值更新位置。
  • 不破坏组件实例。

最好能够从服务而非OverlayRef的组件实例中调用。

为清晰起见,请编辑1: 给定以下PositionStrategyOverlayRef.updatePosition()似乎不适用,因为需要重新计算px。 *注意 window.innerWidth

      private setChannelPosition(): PositionStrategy {
        const chatWidth = 280;
        const chatSpace = 5;
        const distanceFromEdge = 80;

        const existingModalCount = this.channelModals.size;
        const numModalsCanFit = 
           Math.floor((window.innerWidth - 2 * distanceFromEdge) / (chatWidth + chatSpace));
        const distFromRight = 
           distanceFromEdge + ((existingModalCount % numModalsCanFit) * (chatWidth + chatSpace));
        return this.overlay.position().global().bottom('0px').right(`${distFromRight}px`);
      }

修改2: 模态是瞬态的。因此,flexibleConnectedTo()的解决方案似乎并不适用,因为任何模态可能会或可能不会被用户以任何顺序关闭。

1 个答案:

答案 0 :(得分:1)

假设制作setChannelPosition()时只打一次OverlayConfig,例如:

export class MyComponent implements OnInit {

  private overlayRef: OverlayRef;

  constructor(
    private overlay: Overlay
  ) { }

  public ngOnInit(): void {
    this.createOverlay();
  }

  @HostListener('window:resize')
  public onResize(): void {
    this.overlayRef.updatePosition();
  }

  private setChannelPosition(): PositionStrategy {
    const chatWidth = 280;
    const chatSpace = 5;
    const distanceFromEdge = 80;

    const existingModalCount = this.channelModals.size;
    const numModalsCanFit =  Math.floor((window.innerWidth - 2 * distanceFromEdge) / (chatWidth + chatSpace));
    const distFromRight = distanceFromEdge + ((existingModalCount % numModalsCanFit) * (chatWidth + chatSpace));
    return this.overlay.position().global().bottom('0px').right(`${distFromRight}px`);
  }

  private createOverlay() {
    const config = new OverlayConfig({
      positionStrategy: this.setChannelPosition()
    });
    this.overlayRef = this.overlay.create(config);
    this.overlayRef.attach(/* template or component*/);
  }

}

因此行this.overlay.position().global().bottom('0px').right( $ {distFromRight} px );仅运行一次,创建了一个GlobalPositionStrategy,底部为0px,而rigth为distFromRight的值时间。

OverlayRef.updatePosition()调用PositionStrategy.apply()实现的GlobalPositionStrategy并根据其属性简单地应用css值(在这种情况下,底值是0px,而rigth是distFromRight的值) setChannelPosition()运行时。

解决方案是让PositionStrategyPositionStrategy.apply()上重新计算。

class MyPositionStrategy implements PositionStrategy {
  public apply(): void {
    /* recalculates */
  }
}

const config = new OverlayConfig({
 positionStrategy: instanceOfMyPositionStrategy 
});

ruff example

在调用PositionStrategy之前,通过调用OverlayRef.updatePosition() 我认为是角材料7的新手来更改OverlayRef.updatePositionStrategy()

@HostListener('window:resize')
public onResize(): void {
  this.overlayRef.updatePositionStrategy(this.setChannelPosition());
  this.overlayRef.updatePosition();
}

因此,setChannelPosition()会运行,并且PositionStrategy会在每次调整窗口大小时发生变化。

ruff example

注意:

有一个类似

的旧解决方案
@HostListener('window:resize')
public onResize(): void {
  this.overlayRef.getConfig().positionStrategy = this.setChannelPosition();
  this.overlayRef.updatePosition();
}

但是getConfig().positionStrategy现在是只读的,不起作用