Angular 2 AutoComplete无法正常工作

时间:2016-07-15 05:27:59

标签: typescript angular autocomplete type-ahead

[当我输入输入(国家/地区列表)时,自动填充会下拉与我的输入匹配的国家/地区列表。但问题是我无法通过鼠标点击[1]

从该列表中选择一个国家/地区

我正在使用angular2并在执行typeahead(autocomplete)时,我对此错误感到震惊

//app.component.js

    enter code here

import {Component, ElementRef} from 'angular2/core';

@Component({
    selector: 'my-app',
    host: {
        '(document:click)': 'handleClick($event)',
    },
    template: `
        <div class="container" >
            <div class="input-field col s12">
              <input id="country" type="text" class="validate filter-input" [(ngModel)]=query (keyup)=filter($event)  (blur)=handleBlur()>
              <label for="country">Country</label>
            </div>
            <div class="suggestions" *ngIf="filteredList.length > 0">
                <ul *ngFor="#item of filteredList;#idx = index" >
                    <li [class.complete-selected]="idx == selectedIdx">
                        <a (click)="select(item)">{{item}}</a>
                    </li>
                </ul>
            </div>
        </div>
        `
})

export class AppComponent {
    public query = '';
    public countries = ["Albania", "Andorra", "Armenia", "Austria", "Azerbaijan", "Belarus", "Belgium", "Bosnia & Herzegovina",
        "Bulgaria", "Croatia", "Cyprus", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Georgia",
        "Germany", "Greece", "Hungary", "Iceland", "Ireland", "Italy", "Kosovo", "Latvia", "Liechtenstein",
        "Lithuania", "Luxembourg", "Macedonia", "Malta", "Moldova", "Monaco", "Montenegro", "Netherlands",
        "Norway", "Poland", "Portugal", "Romania", "Russia", "San Marino", "Serbia", "Slovakia",
        "Slovenia", "Spain", "Sweden", "Switzerland", "Turkey", "Ukraine", "United Kingdom", "Vatican City"];
    public filteredList = [];
    public elementRef;
    selectedIdx: number;

    constructor(myElement: ElementRef) {
        this.elementRef = myElement;
        this.selectedIdx = -1;
    }

    filter(event: any) {
        if (this.query !== "") {
            this.filteredList = this.countries.filter(function (el) {
                return (el.toLowerCase().substr(0,this.query.length) === this.query.toLowerCase()) == true;
            }.bind(this));
            if (event.code == "ArrowDown" && this.selectedIdx < this.filteredList.length) {
                this.selectedIdx++;
            } else if (event.code == "ArrowUp" && this.selectedIdx > 0) {
                this.selectedIdx--;
            }
        } else {
            this.filteredList = [];
        }
    }

    select(item) {
        this.query = item;
        this.filteredList = [];
        this.selectedIdx = -1;
    }

    handleBlur() {
        if (this.selectedIdx > -1) {
            this.query = this.filteredList[this.selectedIdx];
        }
        this.filteredList = [];
        this.selectedIdx = -1;
    }

    handleClick(event) {
        var clickedComponent = event.target;
        var inside = false;
        do {
            if (clickedComponent === this.elementRef.nativeElement) {
                inside = true;
            }
            clickedComponent = clickedComponent.parentNode;
        } while (clickedComponent);
        if `enter code here`(!inside) {
            this.filteredList = [];
        }
        this.selectedIdx = -1;
    }


}`

____________________________________________________________________________________________________________________________________________________
//main.ts
import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);

____________________________________________________________________________________________________________________________________________________
//index.html
<html>
  <head>
    <title>MasaCafe</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">    

    <!-- 1. Load libraries -->
    <!-- IE required polyfills, in this exact order -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>

    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>

    <script src="https://code.jquery.com/jquery-2.2.1.min.js" ></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>

    <link rel="stylesheet" href="style.css"></link>

    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>

  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>

</html>


What did I do wrong?


  [1]: http://i.stack.imgur.com/i06n3.png

2 个答案:

答案 0 :(得分:2)

  1. 您的input元素具有模糊处理程序,该处理程序优先于(我的理解)对具有in li元素的元素的click事件。单击自动建议时,浏览器将触发onb​​lur事件,该事件将重置AppComponent中的filteredList。

  2. 重置filteredList将从dom中删除自动建议列表,因为您在模板中使用了* ngIf,从而使click事件无效。因此,永远不会调用click事件。

  3. 尝试删除模糊处理程序,这应该按预期工作。我的意思是点击自动建议项目。

  4. 我建议在锚元素上使用(mousedown)而不是(click)。同样在mousedown事件处理程序中使用event.stopPropagation,因此您的自动建议列表不会失去焦点。

      select(event,item) {
        this.query = item;
        this.filteredList = [];
        this.selectedIdx = -1;
        event.stopPropagation();
      }
    
  5. &#13;
    &#13;
    <div class="container">
      <div class="input-field col s12">
        <input id="country" type="text" class="validate filter-input" [(ngModel)]=query (keyup)=filter($event) (blur)="handleBlur()">
        <div class="suggestions" *ngIf="filteredList.length > 0">
          <ul>
            <li *ngFor="let item of filteredList;let idx = index" [class.complete-selected]="idx == selectedIdx"
                (mousedown)="select($event,item)">
              {{item}}
            </li>
          </ul>
        </div>
      </div>
      <label for="country">Country</label>
    </div>
    &#13;
    &#13;
    &#13;

    希望这有帮助。

答案 1 :(得分:1)

我为Angular2 Auto完成了一个模块。它接受一个Array,一个URL,一个对象内的Array或一个对象Array作为输入。您还可以添加自定义CSS来设置控件的样式。用法示例和下载链接可在以下位置找到: ang2-autocomplete