我正在使用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
在文本框中输入字符,然后向上滚动
答案 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中放置以下代码。
我们可以将以下代码放置在以下任何文件中
ngb-typeahead-window {
max-height: 200px;
overflow-y: auto;
overflow-x: hidden;
}
工作代码 stackblitz 链接:https://stackblitz.com/edit/angular-qpzsfv