Skip to content

Commit

Permalink
fix(typeahead): Added form support (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinistro authored and valorkin committed Jul 14, 2016
1 parent 53c7fd1 commit fa54e46
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 38 deletions.
31 changes: 14 additions & 17 deletions components/typeahead/typeahead.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import {
Directive, Input, Output, HostListener, EventEmitter, OnInit, ElementRef,
Renderer, DynamicComponentLoader, ComponentRef, ReflectiveInjector, provide, ViewContainerRef
} from '@angular/core';
import {NgModel} from '@angular/forms';
import {NgControl, FormControl} from '@angular/forms';
import {TypeaheadUtils} from './typeahead-utils';
import {TypeaheadContainerComponent} from './typeahead-container.component';
import {TypeaheadOptions} from './typeahead-options.class';

import {Observable} from 'rxjs/Rx';
import {Observable} from 'rxjs/Observable';

import 'rxjs/add/observable/from';
import 'rxjs/add/operator/debounceTime';
Expand All @@ -21,13 +21,10 @@ import {global} from '@angular/core/src/facade/lang';
const KeyboardEvent = (global as any).KeyboardEvent as KeyboardEvent;
/* tslint:enable */

// https://github.com/angular/angular/blob/master/modules/@angular/src/core/forms/directives/shared.ts
function setProperty(renderer:Renderer, elementRef:ElementRef, propName:string, propValue:any):void {
renderer.setElementProperty(elementRef.nativeElement, propName, propValue);
}

@Directive({
selector: '[typeahead][ngModel]'
/* tslint:disable */
selector: '[typeahead][ngModel],[typeahead][formControlName]'
/* tslint:enable */
})
export class TypeaheadDirective implements OnInit {
@Output() public typeaheadLoading:EventEmitter<boolean> = new EventEmitter<boolean>(false);
Expand Down Expand Up @@ -62,7 +59,7 @@ export class TypeaheadDirective implements OnInit {
private placement:string = 'bottom-left';
private popup:Promise<ComponentRef<any>>;

private cd:NgModel;
private ngControl:NgControl;
private viewContainerRef:ViewContainerRef;
private element:ElementRef;
private renderer:Renderer;
Expand Down Expand Up @@ -142,10 +139,10 @@ export class TypeaheadDirective implements OnInit {
}
}

public constructor(cd:NgModel, viewContainerRef:ViewContainerRef, element:ElementRef,
public constructor(control:NgControl, viewContainerRef:ViewContainerRef, element:ElementRef,
renderer:Renderer, loader:DynamicComponentLoader) {
this.element = element;
this.cd = cd;
this.ngControl = control;
this.viewContainerRef = viewContainerRef;
this.renderer = renderer;
this.loader = loader;
Expand Down Expand Up @@ -176,8 +173,8 @@ export class TypeaheadDirective implements OnInit {
let valueStr:string = ((typeof value === 'object' && this.typeaheadOptionField)
? value[this.typeaheadOptionField]
: value).toString();
this.cd.viewToModelUpdate(valueStr);
setProperty(this.renderer, this.element, 'value', valueStr);
this.ngControl.viewToModelUpdate(valueStr);
(this.ngControl.control as FormControl).updateValue(valueStr);
this.hide();
}

Expand All @@ -204,8 +201,8 @@ export class TypeaheadDirective implements OnInit {
this.container.parent = this;
// This improves the speedas it won't have to be done for each list item
let normalizedQuery = (this.typeaheadLatinize
? TypeaheadUtils.latinize(this.cd.model)
: this.cd.model).toString()
? TypeaheadUtils.latinize(this.ngControl.control.value)
: this.ngControl.control.value).toString()
.toLowerCase();
this.container.query = this.typeaheadSingleWords
? TypeaheadUtils.tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
Expand Down Expand Up @@ -325,8 +322,8 @@ export class TypeaheadDirective implements OnInit {
if (this.container && this._matches.length > 0) {
// This improves the speedas it won't have to be done for each list item
let normalizedQuery = (this.typeaheadLatinize
? TypeaheadUtils.latinize(this.cd.model)
: this.cd.model).toString()
? TypeaheadUtils.latinize(this.ngControl.control.value)
: this.ngControl.control.value).toString()
.toLowerCase();
this.container.query = this.typeaheadSingleWords
? TypeaheadUtils.tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
Expand Down
55 changes: 36 additions & 19 deletions demo/components/typeahead/typeahead-demo.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,43 @@
<div class='container-fluid'>
<h4>Static arrays</h4>
<pre class="card card-block card-header">Model: {{selected | json}}</pre>
<input [(ngModel)]="selected"
[typeahead]="states"
(typeaheadOnSelect)="typeaheadOnSelect($event)"
class="form-control">
<!-- Static arrays -->
<h4>Static arrays</h4>
<pre class="card card-block card-header">Model: {{selected | json}}</pre>
<input [(ngModel)]="selected"
[typeahead]="states"
(typeaheadOnSelect)="typeaheadOnSelect($event)"
class="form-control">

<!-- Asynchronous results -->
<h4>Asynchronous results</h4>
<pre class="card card-block card-header">Model: {{asyncSelected | json}}</pre>
<input [(ngModel)]="asyncSelected"
[typeahead]="dataSource"
(typeaheadLoading)="changeTypeaheadLoading($event)"
(typeaheadNoResults)="changeTypeaheadNoResults($event)"
(typeaheadOnSelect)="typeaheadOnSelect($event)"
[typeaheadOptionsLimit]="7"
[typeaheadOptionField]="'name'"
placeholder="Locations loaded with timeout"
class="form-control">
<div *ngIf="typeaheadLoading===true">
<i class="glyphicon glyphicon-refresh ng-hide" style=""></i>
</div>
<div *ngIf="typeaheadNoResults===true" class="" style="">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>

<h4>Asynchronous results</h4>
<pre class="card card-block card-header">Model: {{asyncSelected | json}}</pre>
<input [(ngModel)]="asyncSelected"
[typeahead]="dataSource"
(typeaheadLoading)="changeTypeaheadLoading($event)"
(typeaheadNoResults)="changeTypeaheadNoResults($event)"
<!--Typeahead inside a form-->
<h4>Typeahead inside a form</h4>
<pre class="card card-block card-header">Model: {{myForm.value.state | json}}</pre>
<form [formGroup]="myForm">
<input formControlName="state"
[typeahead]="states"
(typeaheadOnSelect)="typeaheadOnSelect($event)"
[typeaheadOptionsLimit]="7"
[typeaheadOptionField]="'name'"
placeholder="Locations loaded with timeout"
placeholder="Typeahead inside a form"
class="form-control">
<div *ngIf="typeaheadLoading===true">
<i class="glyphicon glyphicon-refresh ng-hide" style=""></i>
</div>
<div *ngIf="typeaheadNoResults===true" class="" style="">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>
</form>


</div>
10 changes: 8 additions & 2 deletions demo/components/typeahead/typeahead-demo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Component} from '@angular/core';
import {CORE_DIRECTIVES} from '@angular/common';
import {FORM_DIRECTIVES} from '@angular/forms';
import {FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES, FormGroup, FormControl} from '@angular/forms';
import {Observable} from 'rxjs/Observable';

import {TYPEAHEAD_DIRECTIVES} from '../../../ng2-bootstrap';
Expand All @@ -10,10 +10,16 @@ let template = require('./typeahead-demo.html');

@Component({
selector: 'typeahead-demo',
directives: [TYPEAHEAD_DIRECTIVES, CORE_DIRECTIVES, FORM_DIRECTIVES],
directives: [TYPEAHEAD_DIRECTIVES, CORE_DIRECTIVES, FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES],
template: template
})
export class TypeaheadDemoComponent {
public stateCtrl:FormControl = new FormControl();

public myForm:FormGroup= new FormGroup({
state: this.stateCtrl
});

public selected:string = '';
public dataSource:Observable<any>;
public asyncSelected:string = '';
Expand Down

0 comments on commit fa54e46

Please sign in to comment.