- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想制作一个自动完成组件,它向服务器发出请求并在屏幕上呈现接收到的值。我试图了解 portal
和 overlay
是如何工作的。现在这是我的自动完成组件
import {
Component, OnInit, Input, Output, EventEmitter, OnDestroy, ViewChild, ViewContainerRef,
ElementRef, Optional
} from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
import { MdOption, ConnectedOverlayDirective, Dir, transformPlaceholder, transformPanel, fadeInContent } from '@angular/material';
import { Subscription } from 'rxjs/Subscription';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subject } from 'rxjs/Subject';
import { AutocompleteConfiguration } from './autocomplete-config.model';
import { SearchState, SearchingService, IBackend } from './../../services/searching.service';
import { ISearchConfig } from './../../models/iSearch-config';
import { IHint } from './../generic-form/generic-form.service';
import { getValueAccessorProviders } from './../../models/custom-value-accessor.builder';
@Component({
selector: 'autocomplete',
templateUrl: './autocomplete.html',
providers: [
SearchingService,
getValueAccessorProviders(AutocompleteComponent)
],
animations: [
transformPlaceholder, transformPanel, fadeInContent
]
})
export class AutocompleteComponent implements OnInit, OnDestroy, ControlValueAccessor {
/** Placeholder to be shown if no value has been selected. */
@Input()
get placeholder() { return this._placeholder; }
set placeholder(value: string) {
this._placeholder = value;
// Must wait to record the trigger width to ensure placeholder width is included.
Promise.resolve(null).then(() => this._triggerWidth = this._getWidth());
}
@Input() hint: IHint = null;
@Input() iconPosition: string = ''; // 'prefix', 'suffix' or 'placeholder-prefix', 'placeholder-suffix'
@Input() autocompleteConfigurtation: AutocompleteConfiguration;
@Input() backend: IBackend;
@ViewChild(ConnectedOverlayDirective) overlayDir: ConnectedOverlayDirective;
/** Trigger that opens the select. */
@ViewChild('triggerRef', { read: ElementRef }) trigger: ElementRef;
@Output() blur: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
@Output() focus: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
get value() {
return this._inputValue;
}
set value(value: any) {
if (String(value) !== String(this._inputValue)) {
this._inputValue = String(value);
}
}
/** Whether or not the overlay panel is open. */
private _panelOpen = false;
/** The currently selected option. */
private _selected: MdOption;
private _placeholder: string;
/**
* The width of the trigger. Must be saved to set the min width of the overlay panel
* and the width of the selected value.
*/
private _triggerWidth: number;
private _inputValue: string = '';
private _focused: boolean = false;
private _disabled: boolean = false;
private onSearchStateChange: BehaviorSubject<SearchState>;
private onModelChangeSubject: Subject<any> = new Subject<any>();
private subscriptions: Subscription[] = [];
private searchState: SearchState = null;
/**
* The x-offset of the overlay panel in relation to the trigger's top start corner.
* This must be adjusted to align the selected option text over the trigger text when
* the panel opens. Will change based on LTR or RTL text direction.
*/
_offsetX = 0;
/**
* The y-offset of the overlay panel in relation to the trigger's top start corner.
* This must be adjusted to align the selected option text over the trigger text.
* when the panel opens. Will change based on the y-position of the selected option.
*/
_offsetY = 0;
/** The value of the select panel's transform-origin property. */
_transformOrigin: string = 'top';
/** The animation state of the placeholder. */
_placeholderState = '';
/**
* This position config ensures that the top "start" corner of the overlay
* is aligned with with the top "start" of the origin by default (overlapping
* the trigger completely). If the panel cannot fit below the trigger, it
* will fall back to a position above the trigger.
*/
_positions = [
{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'top',
},
{
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'bottom',
},
];
/** The scroll position of the overlay panel, calculated to center the selected option. */
private _scrollTop = 0;
constructor(
private searchBuilder: SearchingService,
@Optional() private _dir: Dir
) { }
ngOnInit() {
this.onSearchStateChange = this.searchBuilder
.createSearchObservable(this.onModelChangeSubject, this.autocompleteConfigurtation.searchConfig, this.backend);
this.setSearchStateChangeSubscription();
}
setSearchStateChangeSubscription() {
this.subscriptions.push(
this.onSearchStateChange.subscribe(newState => {
debugger
this.searchState = newState;
// this._calculateOverlayPosition();
this._placeholderState = this._isRtl() ? 'floating-rtl' : 'floating-ltr';
this._panelOpen = newState && newState.responseObject && newState.responseObject.length > 0;
})
);
}
onModelChange(inputValue) {
this.value = inputValue;
this._onChangeCallback(this._inputValue);
this._onTouchedCallback();
this._activateSearch(this.value);
}
// From ControlValueAccessor interface
// the ngModel init or form write value
writeValue(value: any) {
this.value = value;
}
// From ControlValueAccessor interface
registerOnChange(fn: any) {
this._onChangeCallback = fn;
}
// From ControlValueAccessor interface
registerOnTouched(fn: any) {
this._onTouchedCallback = fn;
}
setDisabledState(isDisabled: boolean) {
this._disabled = isDisabled;
}
close() {
}
ngOnDestroy() {
this.subscriptions.forEach(val => val.unsubscribe());
this.subscriptions = [];
this.onModelChangeSubject.unsubscribe();
}
/**
* Sets the scroll position of the scroll container. This must be called after
* the overlay pane is attached or the scroll container element will not yet be
* present in the DOM.
*/
_setScrollTop(): void {
const scrollContainer =
this.overlayDir.overlayRef.overlayElement.querySelector('.md-select-panel');
scrollContainer.scrollTop = this._scrollTop;
}
/** The width of the trigger element. This is necessary to match
* the overlay width to the trigger width.
*/
_getWidth(): number {
return this._getTriggerRect().width;
}
_isRtl(): boolean {
return this._dir ? this._dir.value === 'rtl' : false;
}
_onPanelDone($event) {
console.log($event);
}
private _getTriggerRect(): ClientRect {
return this.trigger.nativeElement.getBoundingClientRect();
}
private _activateSearch(value) {
if (this._disabled || !this.focus) {
return;
}
this.onModelChangeSubject.next(value);
}
private _handleFocus($event) {
this._focused = true;
if (this.autocompleteConfigurtation.activateOnFocus) {
this._activateSearch(this.value);
}
this.focus.emit($event);
}
private _handleBlur($event) {
this._focused = false;
this._onTouchedCallback();
this.blur.emit($event);
}
private _onChangeCallback(_: any) { }
private _onTouchedCallback() { }
}
这是html
<md-input type="text"
#triggerRef
#origin="cdkOverlayOrigin"
cdk-overlay-origin
[disabled]="_disabled"
[(ngModel)]="value"
(blur)="_handleBlur($event)"
(focus)="_handleFocus($event)"
(ngModelChange)="onModelChange($event)">
<md-placeholder *ngIf="placeholder || iconPosition.indexOf('placeholder') !== -1">
<i *ngIf="iconPosition === 'placeholder-prefix'" class="material-icons app-input-icon">{{field.icon}}</i>
{{placeholder}}
<i *ngIf="iconPosition === 'placeholder-suffix'" class="material-icons app-input-icon">{{field.icon}}</i>
</md-placeholder>
<span md-prefix>
<md-icon *ngIf="iconPosition === 'prefix'">field.icon</md-icon>
</span>
<span md-suffix>
<md-icon *ngIf="iconPosition === 'suffix'">field.icon</md-icon>
</span>
<md-hint *ngIf="hint" [align]="hint.align">
{{hint.value}}
</md-hint>
</md-input>
<template
cdk-connected-overlay
hasBackdrop
backdropClass="cdk-overlay-transparent-backdrop"
[origin]="origin"
[open]="_panelOpen"
[positions]="_positions"
[minWidth]="_triggerWidth"
[offsetY]="_offsetY"
[offsetX]="_offsetX"
(backdropClick)="close()"
(attach)="_setScrollTop()">
<div class="md-select-panel"
[@transformPanel]="'showing'"
[style.transformOrigin]="_transformOrigin"
[class.md-select-panel-done-animating]="_panelDoneAnimating"
(@transformPanel.done)="_onPanelDone()"
(keydown)="log($event)">
<div class="md-select-content" [@fadeInContent]="'showing'">
<md-option *ngFor="let option of searchState?.responseObject"
[value]="option.value">
{{ option?.text }}
</md-option>
</div>
</div>
</template>
该组件可以正常工作,并按应有的方式呈现叠加层。覆盖容器呈现选项唯一的问题是宽度。我阅读了门户网站和叠加层的核心概念,但我想了解它是如何真正与 Angular 一起工作的。
谁能解释一下它是如何工作的?或者至少我如何控制它的宽度?
最佳答案
I managed to use the overlay component if anyone wants an example you can try to have a look here I will try to add comments about how I think it works. Also some documentation about it and how to use it will be more then welcomed from @angular/material. I think is very usable to create third party components which needs to be rendered in the dome tree to not have problems with overflow hidden or translate3d
关于Angular 2 Material - overlay 和 portal 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41749269/
我有一个带有用于覆盖的 css 类的面板,其中包含一个不应该透明的 div
我已经尝试了 2 天不让 openldap 的 memberof overlay 工作并给出一些实际结果。我的数据库配置: database bdb suffix "dc=exampl
我想使用 jquery ui 弹出一个模式对话框,其中覆盖层是全黑的。我知道我可以在主题中设置它,但我不希望所有对话框都有黑色覆盖。只是其中之一。 有没有办法在每个对话框的基础上配置对话框的背景(覆盖
我是新来的,所以如果我问错了问题或忘记了什么,我先道歉。我尝试了其他问题/答案中的内容,但无法解决我的问题。 我在 div1 上有一个简单的叠加 div2。 div1 里面有一个 svg。 svg 向
我正在使用 npm overlay-navbar 模块创建一个 overlay-navbar https://www.npmjs.com/package/overlay-navbar但是我收到一个错误
我只想为我在 nix 的叠加层中定义的构建应用配置点。 也就是我要设置 permittedInsecurePackages = [ "webkitgtk-2.4.11" ]; 在叠加层中。我
我需要有关如何正确使用 Google Maps API v3 自定义叠加层的 onRemove() 方法的帮助。我在 Google map 上有一个标记,单击该标记时,将显示一个 d3 圆环图,该图将
首先这是我正在使用和尝试做的事情: 此效果的最小设置:flowplayer.org/tools/demos/overlay/index.html 然后是 Apple Leopard 预览效果:flow
我的问题真的很简单...... 想象一张代表您家周围的街道和建筑物的背景图片,请注意这是专门制作的图片。此图像( View )是可缩放的,到目前为止一切都很好。类似于 map ,但使用图像代替。 现在
我正在使用花式框在行内 div 中打开各种编辑功能。我使用ajax获取div内容,将其移动到div中,然后在Fancybox中打开div。大多数情况下效果很好。一些编辑 block 中包含 ckedi
在应用程序中扩展 OSMdroid Overlay 类时 import org.osmdroid.views.overlay.Overlay; ... public class MapOverlayA
我的应用程序有问题,其中包括 osmdroid。每次我尝试在我的设备上运行该应用程序并触摸 map 时,该应用程序都会崩溃,并且出现此错误: 2018-10-02 14:11:45.191 1
我如何在UWP应用程序中实现这样的功能?使用案例:静态图像包含蓝点(覆盖),使用户有机会在蓝点上单击/悬停以了解更多信息。当用户悬停/单击蓝点时,会弹出一个文本来描述图像中的内容。。1)如何在静态图像
仅适用于 iOS:当您将叠加层添加到 Web HTML 用户界面时,您无法通过设置 overflow: hidden on the body 或 html 来阻止底层页面滚动到叠加层之外。这在桌面和
我是 HTML/CSS 新手。我创建了这个侧边栏,当单击时,它会从左侧滑动,滑动时会显示不透明背景。不幸的是,图像显示在不透明覆盖层的顶部,我找不到让它停止在不透明覆盖层上如此明亮地显示的问题。我正在
是否可以创建一个窗口作为另一个窗口的叠加层,例如,您可以在窗口的标题栏或状态栏中显示一个图标? 为了这个问题的目的假设: 该窗口是一个外部窗口(不属于我的应用程序) 叠加层为 16x16 像素并具有透
在 bokeh Holoviews 画廊中,有一个名为“Scatter economic”的示例。 http://holoviews.org/gallery/demos/bokeh/scatter_e
制作 gwt 覆盖类型的深拷贝的最佳方法是什么? 我正在寻找一个函数或库来检查 GWT 覆盖并克隆它。它必须能够克隆包含的数组或对象。 谢谢 最佳答案 我会考虑两种方式。大多数时候覆盖对象与 JSON
最近,我尝试创建一个 Ionic 侧边菜单。我想让侧面菜单覆盖联系人。 但是,我不想推送内容。 --> fu
我正在尝试在另一个正在运行的应用程序上方创建一个覆盖窗口。 让我们说火狐。我通过使用实现 创建窗口 win = XCreateWindow( display, *firefoxwindow,
我是一名优秀的程序员,十分优秀!