Переместите CdkConnectedOverlay на прокрутку - PullRequest
3 голосов
/ 25 июня 2019

Я пытаюсь использовать CdkConnectedOverlay для отображения наложения при нажатии кнопки.В основном это работает, но оверлей не перемещается при прокрутке.Я уверен, что есть что-то маленькое, что мне не хватает, но я не могу понять, насколько я понимаю.

Я использую Angular 7.2.8 и Angular CDK 7.3.3

Мысльэто может быть связано с отсутствующими стилями CDK (аналогично this ), но я импортировал их;если бы стили отсутствовали, я бы ожидал, что они не будут отображаться правильно в первую очередь.Мой просто не перемещается на свитке.

Шаблон:

<button
  (click)="isOpen = !isOpen"
  cdkOverlayOrigin
  #trigger="cdkOverlayOrigin"
>Show</button>

<ng-template
  cdkConnectedOverlay
  [cdkConnectedOverlayOrigin]="trigger"
  [cdkConnectedOverlayOpen]="isOpen"
>
 Popover content
</ng-template>

Компонент:

@Component ( {
  selector: 'app-popover',
  templateUrl: './popover.component.html',
  styleUrls: [ './popover.component.css' ],
  changeDetection: ChangeDetectionStrategy.OnPush,
} )
export class PopoverComponent {
  isOpen: boolean = false;
}

И Plunkr, показывающий проблему: https://stackblitz.com/edit/angular-7-popover

Обновление :

Проблема изменения положения прокрутки возникает только в том случае, если всплывающее окно находится в элементе, который переполняет своего родителя с помощью overflow: auto.Если страница переполнена, то она работает нормально.Вы можете увидеть это поведение с помощью следующего шаблона

<div style="height: 300px; overflow-y: auto">
  <!-- Scroll re-positioning does not work when scrolling in here -->
  <div style="height: 100px"></div>
  <app-popover>
    Popover content
  </app-popover>
  <div style="height: 400px"></div>
</div>

<div style="height: 100px;"></div>
<!-- Scroll re-positioning works when scrolling here -->
<app-popover>
  Popover content
</app-popover>
<div style="height: 1200px;"></div>

Я также обновил стек стека, чтобы показать эту проблему.

1 Ответ

0 голосов
/ 27 июня 2019

cdk документация иногда непроста для понимания, и повсюду в ней скрыты драгоценные камни:)

здесь говорится, что

Каждая стратегия обычно внедряет ScrollDispatcher (из @ angular / cdk / scrolling), чтобы получать уведомления о том, когда происходит прокрутка.

что я понимаю из этого предложения, так это то, что Overlay перемещается в ответ на события из ScrollDispatcher. Итак, откуда эти события прокрутки?

к сожалению, в документации нет никакой информации об этом. Итак, я взглянул на коды и нашел этот

  /** Sets up the global scroll listeners. */
  private _addGlobalListener() {
    this._globalSubscription = this._ngZone.runOutsideAngular(() => {
      return fromEvent(window.document, 'scroll').subscribe(() => this._scrolled.next());
    });
}

, что означает ScrollDispatcher прослушивания событий прокрутки в окне по умолчанию .

в вашем случае выше он реагирует на события, когда прокручивается окно, но не внутренний контейнер. это соответствует информации, которую мы собрали до сих пор.

здесь мы можем сделать вывод, что Overlay не уведомляется о событиях прокрутки, которые происходят во внутреннем контейнере, и все, что нам нужно сделать, - это зарегистрировать внутренний контейнер с ScrollDispatcher

в этот момент директива cdkScrollable приходит на помощь, и размещение cdkScrollable на внутреннем контейнере с прокруткой решает проблему.

<div cdkScrollable style="height: 300px; overflow-y: auto">

вот рабочая демоверсия

...