实现自动完成
Implementing autocomplete
我找不到适合 Angular2 的自动完成组件。任何我可以将键标签对象列表传递给并在 input
字段上自动完成的东西。
Kendo 尚不支持 Angular 2,它是我们内部主要使用的。 Angular Material 似乎也不支持 Angular 2。
任何人都可以指出正确的方向或让我知道他们在使用什么吗?
这是我到目前为止构建的。太差了,我想找个好看的。
import {Component, EventEmitter, Input, Output} from 'angular2/core';
import {Control} from 'angular2/common';
import {Observable} from 'rxjs/Observable';
import {SimpleKeyValue} from '../models/simple-key-value'
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
@Component({
selector: 'general-typeahead',
template: ` <div>
<div class="input-group">
<input type="text" [ngFormControl] = "term" class="form-control" placeholder={{placeHolder}} >
</div>
<ul>
<li class="item" *ngFor="#item of matchingItems" (click)="selectItem(item)">
{{item.value}}
</li>
</ul>
</div>`
})
export class GeneralTypeahead {
matchingItems: Array<SimpleKeyValue>;
term = new Control();
@Input() allItems: Array<SimpleKeyValue>;
@Input() placeHolder: string;
@Output() onSelectItem = new EventEmitter<SimpleKeyValue>();
constructor() {
this.term.valueChanges
.distinctUntilChanged()
.debounceTime(200)
.subscribe((term : string) => this.matchingItems = this.allItems.filter(sl => sl.value.toLowerCase().indexOf(term.toLowerCase()) > -1));
}
selectItem(sl: SimpleKeyValue) {
this.onSelectItem.emit(sl);
}
}
我想你可以使用 typeahead.js
。它有打字稿定义。所以我想如果你使用 typescript 进行开发,它会很容易使用。
更新: 这个答案导致了 ng2-completer
Angular2 自动完成组件的开发。
这是 Angular2 的现有自动完成组件列表:
感谢 @dan-cancro 提出的想法
为那些希望创建自己的指令的人保留原始答案:
要显示自动完成列表,我们首先需要一个 attribute directive,它将 return 基于输入文本的建议列表,然后将它们显示在下拉列表中。
该指令有 2 个选项来显示列表:
- 获取对 nativeElement 的引用并直接操作 DOM
- 使用 DynamicComponentLoader 动态加载列表组件
在我看来,第二种方法是更好的选择,因为它使用 angular 2 个核心机制,而不是通过直接使用 DOM 来绕过它们,因此我将使用这种方法。
这是指令代码:
"use strict";
import {Directive, DynamicComponentLoader, Input, ComponentRef, Output, EventEmitter, OnInit, ViewContainerRef} from "@angular/core";
import {Promise} from "es6-promise";
import {AutocompleteList} from "./autocomplete-list";
@Directive({
selector: "[ng2-autocomplete]", // The attribute for the template that uses this directive
host: {
"(keyup)": "onKey($event)" // Liten to keyup events on the host component
}
})
export class AutocompleteDirective implements OnInit {
// The search function should be passed as an input
@Input("ng2-autocomplete") public search: (term: string) => Promise<Array<{ text: string, data: any }>>;
// The directive emits ng2AutocompleteOnSelect event when an item from the list is selected
@Output("ng2AutocompleteOnSelect") public selected = new EventEmitter();
private term = "";
private listCmp: ComponentRef<AutocompleteList> = undefined;
private refreshTimer: any = undefined;
private searchInProgress = false;
private searchRequired = false;
constructor( private viewRef: ViewContainerRef, private dcl: DynamicComponentLoader) { }
/**
* On key event is triggered when a key is released on the host component
* the event starts a timer to prevent concurrent requests
*/
public onKey(event: any) {
if (!this.refreshTimer) {
this.refreshTimer = setTimeout(
() => {
if (!this.searchInProgress) {
this.doSearch();
} else {
// If a request is in progress mark that a new search is required
this.searchRequired = true;
}
},
200);
}
this.term = event.target.value;
if (this.term === "" && this.listCmp) {
// clean the list if the search term is empty
this.removeList();
}
}
public ngOnInit() {
// When an item is selected remove the list
this.selected.subscribe(() => {
this.removeList();
});
}
/**
* Call the search function and handle the results
*/
private doSearch() {
this.refreshTimer = undefined;
// if we have a search function and a valid search term call the search
if (this.search && this.term !== "") {
this.searchInProgress = true;
this.search(this.term)
.then((res) => {
this.searchInProgress = false;
// if the term has changed during our search do another search
if (this.searchRequired) {
this.searchRequired = false;
this.doSearch();
} else {
// display the list of results
this.displayList(res);
}
})
.catch(err => {
console.log("search error:", err);
this.removeList();
});
}
}
/**
* Display the list of results
* Dynamically load the list component if it doesn't exist yet and update the suggestions list
*/
private displayList(list: Array<{ text: string, data: any }>) {
if (!this.listCmp) {
this.dcl.loadNextToLocation(AutocompleteList, this.viewRef)
.then(cmp => {
// The component is loaded
this.listCmp = cmp;
this.updateList(list);
// Emit the selectd event when the component fires its selected event
(<AutocompleteList>(this.listCmp.instance)).selected
.subscribe(selectedItem => {
this.selected.emit(selectedItem);
});
});
} else {
this.updateList(list);
}
}
/**
* Update the suggestions list in the list component
*/
private updateList(list: Array<{ text: string, data: any }>) {
if (this.listCmp) {
(<AutocompleteList>(this.listCmp.instance)).list = list;
}
}
/**
* remove the list component
*/
private removeList() {
this.searchInProgress = false;
this.searchRequired = false;
if (this.listCmp) {
this.listCmp.destroy();
this.listCmp = undefined;
}
}
}
该指令动态加载下拉组件,这是使用 bootstrap 4:
的此类组件的示例
"use strict";
import {Component, Output, EventEmitter} from "@angular/core";
@Component({
selector: "autocomplete-list",
template: `<div class="dropdown-menu search-results">
<a *ngFor="let item of list" class="dropdown-item" (click)="onClick(item)">{{item.text}}</a>
</div>`, // Use a bootstrap 4 dropdown-menu to display the list
styles: [".search-results { position: relative; right: 0; display: block; padding: 0; overflow: hidden; font-size: .9rem;}"]
})
export class AutocompleteList {
// Emit a selected event when an item in the list is selected
@Output() public selected = new EventEmitter();
public list;
/**
* Listen for a click event on the list
*/
public onClick(item: {text: string, data: any}) {
this.selected.emit(item);
}
}
要在另一个组件中使用该指令,您需要导入该指令,将其包含在组件指令中,并为其提供搜索功能和事件处理程序以供选择:
"use strict";
import {Component} from "@angular/core";
import {AutocompleteDirective} from "../component/ng2-autocomplete/autocomplete";
@Component({
selector: "my-cmp",
directives: [AutocompleteDirective],
template: `<input class="form-control" type="text" [ng2-autocomplete]="search()" (ng2AutocompleteOnSelect)="onItemSelected($event)" autocomplete="off">`
})
export class MyComponent {
/**
* generate a search function that returns a Promise that resolves to array of text and optionally additional data
*/
public search() {
return (filter: string): Promise<Array<{ text: string, data: any }>> => {
// do the search
resolve({text: "one item", data: null});
};
}
/**
* handle item selection
*/
public onItemSelected(selected: { text: string, data: any }) {
console.log("selected: ", selected.text);
}
}
更新:代码兼容angular2 rc.1
PrimeNG 有一个原生的自动完成组件,具有模板和多选等高级功能。
我知道你已经有了几个答案,但我遇到了类似的情况,我的团队不想依赖繁重的库或与 bootstrap 相关的任何东西,因为我们使用的是 material 所以我制作了我们自己的自动完成控件,使用 material-like 样式,你可以使用我的 autocomplete 或者至少你可以看看给你一些指导,没有太多关于简单示例的文档关于如何上传要在 NPM 上共享的组件。
我已经为 anuglar2 自动完成创建了一个模块
在此模块中,您可以使用数组或 url
npm link : ang2-autocomplete
我已经构建了一个相当简单、可重用且功能强大的 Angular2 自动完成组件,该组件基于此 answer/other 教程中有关此主题和其他主题的一些想法。它绝不是全面的,但如果您决定构建自己的,可能会有所帮助。
组件:
import { Component, Input, Output, OnInit, ContentChild, EventEmitter, HostListener } from '@angular/core';
import { Observable } from "rxjs/Observable";
import { AutoCompleteRefDirective } from "./autocomplete.directive";
@Component({
selector: 'autocomplete',
template: `
<ng-content></ng-content>
<div class="autocomplete-wrapper" (click)="clickedInside($event)">
<div class="list-group autocomplete" *ngIf="results">
<a [routerLink]="" class="list-group-item" (click)="selectResult(result)" *ngFor="let result of results; let i = index" [innerHTML]="dataMapping(result) | highlight: query" [ngClass]="{'active': i == selectedIndex}"></a>
</div>
</div>
`,
styleUrls: ['./autocomplete.component.css']
})
export class AutoCompleteComponent implements OnInit {
@ContentChild(AutoCompleteRefDirective)
public input: AutoCompleteRefDirective;
@Input() data: (searchTerm: string) => Observable<any[]>;
@Input() dataMapping: (obj: any) => string;
@Output() onChange = new EventEmitter<any>();
@HostListener('document:click', ['$event'])
clickedOutside($event: any): void {
this.clearResults();
}
public results: any[];
public query: string;
public selectedIndex: number = 0;
private searchCounter: number = 0;
ngOnInit(): void {
this.input.change
.subscribe((query: string) => {
this.query = query;
this.onChange.emit();
this.searchCounter++;
let counter = this.searchCounter;
if (query) {
this.data(query)
.subscribe(data => {
if (counter == this.searchCounter) {
this.results = data;
this.input.hasResults = data.length > 0;
this.selectedIndex = 0;
}
});
}
else this.clearResults();
});
this.input.cancel
.subscribe(() => {
this.clearResults();
});
this.input.select
.subscribe(() => {
if (this.results && this.results.length > 0)
{
this.selectResult(this.results[this.selectedIndex]);
}
});
this.input.up
.subscribe(() => {
if (this.results && this.selectedIndex > 0) this.selectedIndex--;
});
this.input.down
.subscribe(() => {
if (this.results && this.selectedIndex + 1 < this.results.length) this.selectedIndex++;
});
}
selectResult(result: any): void {
this.onChange.emit(result);
this.clearResults();
}
clickedInside($event: any): void {
$event.preventDefault();
$event.stopPropagation();
}
private clearResults(): void {
this.results = [];
this.selectedIndex = 0;
this.searchCounter = 0;
this.input.hasResults = false;
}
}
组件CSS:
.autocomplete-wrapper {
position: relative;
}
.autocomplete {
position: absolute;
z-index: 100;
width: 100%;
}
指令:
import { Directive, Input, Output, HostListener, EventEmitter } from '@angular/core';
@Directive({
selector: '[autocompleteRef]'
})
export class AutoCompleteRefDirective {
@Input() hasResults: boolean = false;
@Output() change = new EventEmitter<string>();
@Output() cancel = new EventEmitter();
@Output() select = new EventEmitter();
@Output() up = new EventEmitter();
@Output() down = new EventEmitter();
@HostListener('input', ['$event'])
oninput(event: any) {
this.change.emit(event.target.value);
}
@HostListener('keydown', ['$event'])
onkeydown(event: any)
{
switch (event.keyCode) {
case 27:
this.cancel.emit();
return false;
case 13:
var hasResults = this.hasResults;
this.select.emit();
return !hasResults;
case 38:
this.up.emit();
return false;
case 40:
this.down.emit();
return false;
default:
}
}
}
高亮管道:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'highlight'
})
export class HighlightPipe implements PipeTransform {
transform(value: string, args: any): any {
var re = new RegExp(args, 'gi');
return value.replace(re, function (match) {
return "<strong>" + match + "</strong>";
})
}
}
实施:
import { Component } from '@angular/core';
import { Observable } from "rxjs/Observable";
import { Subscriber } from "rxjs/Subscriber";
@Component({
selector: 'home',
template: `
<autocomplete [data]="getData" [dataMapping]="dataMapping" (onChange)="change($event)">
<input type="text" class="form-control" name="AutoComplete" placeholder="Search..." autocomplete="off" autocompleteRef />
</autocomplete>
`
})
export class HomeComponent {
getData = (query: string) => this.search(query);
// The dataMapping property controls the mapping of an object returned via getData.
// to a string that can be displayed to the use as an option to select.
dataMapping = (obj: any) => obj;
// This function is called any time a change is made in the autocomplete.
// When the text is changed manually, no object is passed.
// When a selection is made the object is passed.
change(obj: any): void {
if (obj) {
// You can do pretty much anything here as the entire object is passed if it's been selected.
// Navigate to another page, update a model etc.
alert(obj);
}
}
private searchData = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
// This function mimics an Observable http service call.
// In reality it's probably calling your API, but today it's looking at mock static data.
private search(query: string): Observable<any>
{
return new Observable<any>((subscriber: Subscriber<any>) => subscriber
.next())
.map(o => this.searchData.filter(d => d.indexOf(query) > -1));
}
}
我想补充一些还没有人提到的内容:ng2-input-autocomplete
NPM:https://www.npmjs.com/package/ng2-input-autocomplete
GitHub: https://github.com/liuy97/ng2-input-autocomplete#readme
我找不到适合 Angular2 的自动完成组件。任何我可以将键标签对象列表传递给并在 input
字段上自动完成的东西。
Kendo 尚不支持 Angular 2,它是我们内部主要使用的。 Angular Material 似乎也不支持 Angular 2。
任何人都可以指出正确的方向或让我知道他们在使用什么吗?
这是我到目前为止构建的。太差了,我想找个好看的。
import {Component, EventEmitter, Input, Output} from 'angular2/core';
import {Control} from 'angular2/common';
import {Observable} from 'rxjs/Observable';
import {SimpleKeyValue} from '../models/simple-key-value'
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
@Component({
selector: 'general-typeahead',
template: ` <div>
<div class="input-group">
<input type="text" [ngFormControl] = "term" class="form-control" placeholder={{placeHolder}} >
</div>
<ul>
<li class="item" *ngFor="#item of matchingItems" (click)="selectItem(item)">
{{item.value}}
</li>
</ul>
</div>`
})
export class GeneralTypeahead {
matchingItems: Array<SimpleKeyValue>;
term = new Control();
@Input() allItems: Array<SimpleKeyValue>;
@Input() placeHolder: string;
@Output() onSelectItem = new EventEmitter<SimpleKeyValue>();
constructor() {
this.term.valueChanges
.distinctUntilChanged()
.debounceTime(200)
.subscribe((term : string) => this.matchingItems = this.allItems.filter(sl => sl.value.toLowerCase().indexOf(term.toLowerCase()) > -1));
}
selectItem(sl: SimpleKeyValue) {
this.onSelectItem.emit(sl);
}
}
我想你可以使用 typeahead.js
。它有打字稿定义。所以我想如果你使用 typescript 进行开发,它会很容易使用。
更新: 这个答案导致了 ng2-completer
Angular2 自动完成组件的开发。
这是 Angular2 的现有自动完成组件列表:
感谢 @dan-cancro 提出的想法
为那些希望创建自己的指令的人保留原始答案:
要显示自动完成列表,我们首先需要一个 attribute directive,它将 return 基于输入文本的建议列表,然后将它们显示在下拉列表中。 该指令有 2 个选项来显示列表:
- 获取对 nativeElement 的引用并直接操作 DOM
- 使用 DynamicComponentLoader 动态加载列表组件
在我看来,第二种方法是更好的选择,因为它使用 angular 2 个核心机制,而不是通过直接使用 DOM 来绕过它们,因此我将使用这种方法。
这是指令代码:
"use strict";
import {Directive, DynamicComponentLoader, Input, ComponentRef, Output, EventEmitter, OnInit, ViewContainerRef} from "@angular/core";
import {Promise} from "es6-promise";
import {AutocompleteList} from "./autocomplete-list";
@Directive({
selector: "[ng2-autocomplete]", // The attribute for the template that uses this directive
host: {
"(keyup)": "onKey($event)" // Liten to keyup events on the host component
}
})
export class AutocompleteDirective implements OnInit {
// The search function should be passed as an input
@Input("ng2-autocomplete") public search: (term: string) => Promise<Array<{ text: string, data: any }>>;
// The directive emits ng2AutocompleteOnSelect event when an item from the list is selected
@Output("ng2AutocompleteOnSelect") public selected = new EventEmitter();
private term = "";
private listCmp: ComponentRef<AutocompleteList> = undefined;
private refreshTimer: any = undefined;
private searchInProgress = false;
private searchRequired = false;
constructor( private viewRef: ViewContainerRef, private dcl: DynamicComponentLoader) { }
/**
* On key event is triggered when a key is released on the host component
* the event starts a timer to prevent concurrent requests
*/
public onKey(event: any) {
if (!this.refreshTimer) {
this.refreshTimer = setTimeout(
() => {
if (!this.searchInProgress) {
this.doSearch();
} else {
// If a request is in progress mark that a new search is required
this.searchRequired = true;
}
},
200);
}
this.term = event.target.value;
if (this.term === "" && this.listCmp) {
// clean the list if the search term is empty
this.removeList();
}
}
public ngOnInit() {
// When an item is selected remove the list
this.selected.subscribe(() => {
this.removeList();
});
}
/**
* Call the search function and handle the results
*/
private doSearch() {
this.refreshTimer = undefined;
// if we have a search function and a valid search term call the search
if (this.search && this.term !== "") {
this.searchInProgress = true;
this.search(this.term)
.then((res) => {
this.searchInProgress = false;
// if the term has changed during our search do another search
if (this.searchRequired) {
this.searchRequired = false;
this.doSearch();
} else {
// display the list of results
this.displayList(res);
}
})
.catch(err => {
console.log("search error:", err);
this.removeList();
});
}
}
/**
* Display the list of results
* Dynamically load the list component if it doesn't exist yet and update the suggestions list
*/
private displayList(list: Array<{ text: string, data: any }>) {
if (!this.listCmp) {
this.dcl.loadNextToLocation(AutocompleteList, this.viewRef)
.then(cmp => {
// The component is loaded
this.listCmp = cmp;
this.updateList(list);
// Emit the selectd event when the component fires its selected event
(<AutocompleteList>(this.listCmp.instance)).selected
.subscribe(selectedItem => {
this.selected.emit(selectedItem);
});
});
} else {
this.updateList(list);
}
}
/**
* Update the suggestions list in the list component
*/
private updateList(list: Array<{ text: string, data: any }>) {
if (this.listCmp) {
(<AutocompleteList>(this.listCmp.instance)).list = list;
}
}
/**
* remove the list component
*/
private removeList() {
this.searchInProgress = false;
this.searchRequired = false;
if (this.listCmp) {
this.listCmp.destroy();
this.listCmp = undefined;
}
}
}
该指令动态加载下拉组件,这是使用 bootstrap 4:
的此类组件的示例"use strict";
import {Component, Output, EventEmitter} from "@angular/core";
@Component({
selector: "autocomplete-list",
template: `<div class="dropdown-menu search-results">
<a *ngFor="let item of list" class="dropdown-item" (click)="onClick(item)">{{item.text}}</a>
</div>`, // Use a bootstrap 4 dropdown-menu to display the list
styles: [".search-results { position: relative; right: 0; display: block; padding: 0; overflow: hidden; font-size: .9rem;}"]
})
export class AutocompleteList {
// Emit a selected event when an item in the list is selected
@Output() public selected = new EventEmitter();
public list;
/**
* Listen for a click event on the list
*/
public onClick(item: {text: string, data: any}) {
this.selected.emit(item);
}
}
要在另一个组件中使用该指令,您需要导入该指令,将其包含在组件指令中,并为其提供搜索功能和事件处理程序以供选择:
"use strict";
import {Component} from "@angular/core";
import {AutocompleteDirective} from "../component/ng2-autocomplete/autocomplete";
@Component({
selector: "my-cmp",
directives: [AutocompleteDirective],
template: `<input class="form-control" type="text" [ng2-autocomplete]="search()" (ng2AutocompleteOnSelect)="onItemSelected($event)" autocomplete="off">`
})
export class MyComponent {
/**
* generate a search function that returns a Promise that resolves to array of text and optionally additional data
*/
public search() {
return (filter: string): Promise<Array<{ text: string, data: any }>> => {
// do the search
resolve({text: "one item", data: null});
};
}
/**
* handle item selection
*/
public onItemSelected(selected: { text: string, data: any }) {
console.log("selected: ", selected.text);
}
}
更新:代码兼容angular2 rc.1
PrimeNG 有一个原生的自动完成组件,具有模板和多选等高级功能。
我知道你已经有了几个答案,但我遇到了类似的情况,我的团队不想依赖繁重的库或与 bootstrap 相关的任何东西,因为我们使用的是 material 所以我制作了我们自己的自动完成控件,使用 material-like 样式,你可以使用我的 autocomplete 或者至少你可以看看给你一些指导,没有太多关于简单示例的文档关于如何上传要在 NPM 上共享的组件。
我已经为 anuglar2 自动完成创建了一个模块 在此模块中,您可以使用数组或 url npm link : ang2-autocomplete
我已经构建了一个相当简单、可重用且功能强大的 Angular2 自动完成组件,该组件基于此 answer/other 教程中有关此主题和其他主题的一些想法。它绝不是全面的,但如果您决定构建自己的,可能会有所帮助。
组件:
import { Component, Input, Output, OnInit, ContentChild, EventEmitter, HostListener } from '@angular/core';
import { Observable } from "rxjs/Observable";
import { AutoCompleteRefDirective } from "./autocomplete.directive";
@Component({
selector: 'autocomplete',
template: `
<ng-content></ng-content>
<div class="autocomplete-wrapper" (click)="clickedInside($event)">
<div class="list-group autocomplete" *ngIf="results">
<a [routerLink]="" class="list-group-item" (click)="selectResult(result)" *ngFor="let result of results; let i = index" [innerHTML]="dataMapping(result) | highlight: query" [ngClass]="{'active': i == selectedIndex}"></a>
</div>
</div>
`,
styleUrls: ['./autocomplete.component.css']
})
export class AutoCompleteComponent implements OnInit {
@ContentChild(AutoCompleteRefDirective)
public input: AutoCompleteRefDirective;
@Input() data: (searchTerm: string) => Observable<any[]>;
@Input() dataMapping: (obj: any) => string;
@Output() onChange = new EventEmitter<any>();
@HostListener('document:click', ['$event'])
clickedOutside($event: any): void {
this.clearResults();
}
public results: any[];
public query: string;
public selectedIndex: number = 0;
private searchCounter: number = 0;
ngOnInit(): void {
this.input.change
.subscribe((query: string) => {
this.query = query;
this.onChange.emit();
this.searchCounter++;
let counter = this.searchCounter;
if (query) {
this.data(query)
.subscribe(data => {
if (counter == this.searchCounter) {
this.results = data;
this.input.hasResults = data.length > 0;
this.selectedIndex = 0;
}
});
}
else this.clearResults();
});
this.input.cancel
.subscribe(() => {
this.clearResults();
});
this.input.select
.subscribe(() => {
if (this.results && this.results.length > 0)
{
this.selectResult(this.results[this.selectedIndex]);
}
});
this.input.up
.subscribe(() => {
if (this.results && this.selectedIndex > 0) this.selectedIndex--;
});
this.input.down
.subscribe(() => {
if (this.results && this.selectedIndex + 1 < this.results.length) this.selectedIndex++;
});
}
selectResult(result: any): void {
this.onChange.emit(result);
this.clearResults();
}
clickedInside($event: any): void {
$event.preventDefault();
$event.stopPropagation();
}
private clearResults(): void {
this.results = [];
this.selectedIndex = 0;
this.searchCounter = 0;
this.input.hasResults = false;
}
}
组件CSS:
.autocomplete-wrapper {
position: relative;
}
.autocomplete {
position: absolute;
z-index: 100;
width: 100%;
}
指令:
import { Directive, Input, Output, HostListener, EventEmitter } from '@angular/core';
@Directive({
selector: '[autocompleteRef]'
})
export class AutoCompleteRefDirective {
@Input() hasResults: boolean = false;
@Output() change = new EventEmitter<string>();
@Output() cancel = new EventEmitter();
@Output() select = new EventEmitter();
@Output() up = new EventEmitter();
@Output() down = new EventEmitter();
@HostListener('input', ['$event'])
oninput(event: any) {
this.change.emit(event.target.value);
}
@HostListener('keydown', ['$event'])
onkeydown(event: any)
{
switch (event.keyCode) {
case 27:
this.cancel.emit();
return false;
case 13:
var hasResults = this.hasResults;
this.select.emit();
return !hasResults;
case 38:
this.up.emit();
return false;
case 40:
this.down.emit();
return false;
default:
}
}
}
高亮管道:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'highlight'
})
export class HighlightPipe implements PipeTransform {
transform(value: string, args: any): any {
var re = new RegExp(args, 'gi');
return value.replace(re, function (match) {
return "<strong>" + match + "</strong>";
})
}
}
实施:
import { Component } from '@angular/core';
import { Observable } from "rxjs/Observable";
import { Subscriber } from "rxjs/Subscriber";
@Component({
selector: 'home',
template: `
<autocomplete [data]="getData" [dataMapping]="dataMapping" (onChange)="change($event)">
<input type="text" class="form-control" name="AutoComplete" placeholder="Search..." autocomplete="off" autocompleteRef />
</autocomplete>
`
})
export class HomeComponent {
getData = (query: string) => this.search(query);
// The dataMapping property controls the mapping of an object returned via getData.
// to a string that can be displayed to the use as an option to select.
dataMapping = (obj: any) => obj;
// This function is called any time a change is made in the autocomplete.
// When the text is changed manually, no object is passed.
// When a selection is made the object is passed.
change(obj: any): void {
if (obj) {
// You can do pretty much anything here as the entire object is passed if it's been selected.
// Navigate to another page, update a model etc.
alert(obj);
}
}
private searchData = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
// This function mimics an Observable http service call.
// In reality it's probably calling your API, but today it's looking at mock static data.
private search(query: string): Observable<any>
{
return new Observable<any>((subscriber: Subscriber<any>) => subscriber
.next())
.map(o => this.searchData.filter(d => d.indexOf(query) > -1));
}
}
我想补充一些还没有人提到的内容:ng2-input-autocomplete
NPM:https://www.npmjs.com/package/ng2-input-autocomplete
GitHub: https://github.com/liuy97/ng2-input-autocomplete#readme