附加后动态更改 Angular material 叠加位置

Change Angular material overlay position dynamically after attaching

有一些叠加层需要在 window-resize 事件后重新定位。

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

这个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() 的解决方案似乎不适用,因为用户可能会或可能不会以任何顺序关闭任何模态。

假设您在制作 OverlayConfig 时只调用 setChannelPosition() 一次,例如:

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 是任何值distFromRightsetChannelPosition() 运行).

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

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

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

ruff example

通过调用 OverlayRef.updatePositionStrategy() new 将调用 OverlayRef.updatePosition() 之前的 PositionStrategy 更改为 angular material 7 我认为

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

因此 setChannelPosition() 运行并且 PositionStrategy 每次 window 调整大小时都会更改。

ruff example

注:

有一个像

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

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