NgbTypeahead组件不会在可滚动组件内滚动

时间:2017-11-30 13:18:01

标签: css angular ng-bootstrap

我正在使用ng-bootstrap的NgbTypeahead组件。我的问题是,当我将typeahead组件放在一个可滚动的组件中并向下滚动时,下拉容器的位置不会改变。

<div style="height: 300px;   overflow-y: auto;">
...
<input id="typeahead-template" type="text" class="form-control [(ngModel)]="model" 
       [ngbTypeahead]="search" [resultTemplate]="rt [inputFormatter]="formatter" />
...
</div>

这可能是一个小的CSS问题,但我找不到解决方案。

以下是plunkr: http://plnkr.co/edit/rxOhDy72YWlLy9U4Ujcd?p=preview

在文本框中输入字符,然后向上滚动

4 个答案:

答案 0 :(得分:1)

要添加垂直滚动条以提前输入结果,可以使用以下方法:

ngb-typeahead-window.dropdown-menu {
    max-height: 500px !important;
    overflow-y: auto;
}

答案 1 :(得分:0)

由于NgbTypeahead不支持滚动,我们需要从组件处理。在Input的keydown上使用showDropdownEle函数。

private isElementInViewport(el, inputElem) {
const rect = el.getBoundingClientRect();
const rectElem = inputElem.getBoundingClientRect();
console.log(rectElem);
return (
  rect.top >= rectElem.bottom &&
  rect.left >= 0 &&
  rect.bottom <= (rectElem.bottom + rect.offsetHeight) &&
  rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
}

public showDropdownEle(event) {
if (event.keyCode === 38 || event.keyCode === 40) {
  if (event.target.nextElementSibling && event.target.nextElementSibling.nodeName === 'NGB-TYPEAHEAD-WINDOW') {
    let activeDropdownEle = (event.keyCode === 40) ? event.target.nextElementSibling.querySelector('.active').nextElementSibling : event.target.nextElementSibling.querySelector('.active').previousElementSibling;
    if (!activeDropdownEle) {
      const allDropdownElems = event.target.nextElementSibling.querySelectorAll('.dropdown-item');
      activeDropdownEle = (event.keyCode === 38) ? allDropdownElems[allDropdownElems.length - 1] : allDropdownElems[0];
    }
    if (!this.isElementInViewport(activeDropdownEle, event.target) && event.keyCode === 40) {
      activeDropdownEle.scrollIntoView(false);
    }
    if (!this.isElementInViewport(activeDropdownEle, event.target) && event.keyCode === 38) {
      activeDropdownEle.scrollIntoView(true);
    }
  }
}
}

答案 2 :(得分:0)

typeahead-scrollable.html文件

<input id="typeahead-scrollable" type="text" class="form-control" (keydown)="typeaheadKeydown($event)" #typeaheadInstance="ngbTypeahead" [(ngModel)]="model" [ngbTypeahead]="search" [resultFormatter]="formatter" 

typeahead-scrollable.ts文件

    @ViewChild('typeaheadInstance')
    private typeaheadInstance: NgbTypeahead;

    typeaheadKeydown($event: KeyboardEvent) {
      if (this.typeaheadInstance.isPopupOpen()) {
        setTimeout(() => {
          const popup = document.getElementById(this.typeaheadInstance.popupId);
          const activeElements = popup.getElementsByClassName('active');
          if (activeElements.length === 1) {
            // activeElements[0].scrollIntoView();
            const elem = (activeElements[0] as any);
            if (typeof elem.scrollIntoViewIfNeeded === 'function') {
              // non standard function, but works (in chrome)...
              elem.scrollIntoViewIfNeeded();
            } else {
              //do custom scroll calculation or use jQuery Plugin or ...
              this.scrollIntoViewIfNeededPolyfill(elem as HTMLElement);
            }
          }
        });
      }
    }

    private scrollIntoViewIfNeededPolyfill(elem: HTMLElement, centerIfNeeded = true) {
      var parent = elem.parentElement,
        parentComputedStyle = window.getComputedStyle(parent, null),
        parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
        parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
        overTop = elem.offsetTop - parent.offsetTop < parent.scrollTop,
        overBottom = (elem.offsetTop - parent.offsetTop + elem.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
        overLeft = elem.offsetLeft - parent.offsetLeft < parent.scrollLeft,
        overRight = (elem.offsetLeft - parent.offsetLeft + elem.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
        alignWithTop = overTop && !overBottom;

      if ((overTop || overBottom) && centerIfNeeded) {
        parent.scrollTop = elem.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + elem.clientHeight / 2;
      }

      if ((overLeft || overRight) && centerIfNeeded) {
        parent.scrollLeft = elem.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + elem.clientWidth / 2;
      }

      if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
        elem.scrollIntoView(alignWithTop);
      }
    }

工作示例:

https://stackblitz.com/edit/angular-utd9ii?file=app%2Ftypeahead-scrollable.ts

答案 3 :(得分:0)

在您的styles.css中放置以下代码。

我们可以将以下代码放置在以下任何文件中

  • Style.css 文件
  • index.html 样式标签
ngb-typeahead-window {
  max-height: 200px;
  overflow-y: auto;
  overflow-x: hidden;
}

工作代码 stackblitz 链接:https://stackblitz.com/edit/angular-qpzsfv