Angular 2 Autocomplete

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
0
down vote

favorite












I've tried to build a fairly simple, reusable and functional Angular2 autocomplete component.



The component:





import Component, Input, Output, OnInit, ContentChild, EventEmitter, HostListener from '@angular/core';
import Observable from "rxjs/Observable";
import AutoCompleteRefDirective from "./autocomplete.directive";

@Component(
selector: 'autocomplete',
templateUrl: './autocomplete.component.html',
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;




The component HTML:





<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>


The component CSS:





.autocomplete-wrapper 
position: relative;


.autocomplete
position: absolute;
z-index: 100;
width: 100%;



The directive:





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:





The highlight pipe:



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>";
)





The implementation:



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));




A few thoughts:



  • The use of both a Component and a Directive isn't ideal but I couldn't figure out a better way to do it.

  • The getData property and search() functions have been separated so as to mimic a real life service call scenario. It took me an age working out how to wire this up using a property and =>! But is there a better way, especially when dealing with async calls?

  • The highlight pipe isn't necessary but it does improve the experience so I figured I'd include it here.

  • I'm leveraging the bootstrap list group in the component, so apologies if you don't have this installed and it looks crap.

  • I had considered combining the keydown events in the directive into a single event, however because I need to return a value from there I decided to keep them separate.

I'm fairly new to Angular2 so would of course appreciate your suggestions and feedback on any aspect of this implementation.







share|improve this question



























    up vote
    0
    down vote

    favorite












    I've tried to build a fairly simple, reusable and functional Angular2 autocomplete component.



    The component:





    import Component, Input, Output, OnInit, ContentChild, EventEmitter, HostListener from '@angular/core';
    import Observable from "rxjs/Observable";
    import AutoCompleteRefDirective from "./autocomplete.directive";

    @Component(
    selector: 'autocomplete',
    templateUrl: './autocomplete.component.html',
    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;




    The component HTML:





    <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>


    The component CSS:





    .autocomplete-wrapper 
    position: relative;


    .autocomplete
    position: absolute;
    z-index: 100;
    width: 100%;



    The directive:





    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:





    The highlight pipe:



    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>";
    )





    The implementation:



    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));




    A few thoughts:



    • The use of both a Component and a Directive isn't ideal but I couldn't figure out a better way to do it.

    • The getData property and search() functions have been separated so as to mimic a real life service call scenario. It took me an age working out how to wire this up using a property and =>! But is there a better way, especially when dealing with async calls?

    • The highlight pipe isn't necessary but it does improve the experience so I figured I'd include it here.

    • I'm leveraging the bootstrap list group in the component, so apologies if you don't have this installed and it looks crap.

    • I had considered combining the keydown events in the directive into a single event, however because I need to return a value from there I decided to keep them separate.

    I'm fairly new to Angular2 so would of course appreciate your suggestions and feedback on any aspect of this implementation.







    share|improve this question























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I've tried to build a fairly simple, reusable and functional Angular2 autocomplete component.



      The component:





      import Component, Input, Output, OnInit, ContentChild, EventEmitter, HostListener from '@angular/core';
      import Observable from "rxjs/Observable";
      import AutoCompleteRefDirective from "./autocomplete.directive";

      @Component(
      selector: 'autocomplete',
      templateUrl: './autocomplete.component.html',
      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;




      The component HTML:





      <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>


      The component CSS:





      .autocomplete-wrapper 
      position: relative;


      .autocomplete
      position: absolute;
      z-index: 100;
      width: 100%;



      The directive:





      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:





      The highlight pipe:



      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>";
      )





      The implementation:



      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));




      A few thoughts:



      • The use of both a Component and a Directive isn't ideal but I couldn't figure out a better way to do it.

      • The getData property and search() functions have been separated so as to mimic a real life service call scenario. It took me an age working out how to wire this up using a property and =>! But is there a better way, especially when dealing with async calls?

      • The highlight pipe isn't necessary but it does improve the experience so I figured I'd include it here.

      • I'm leveraging the bootstrap list group in the component, so apologies if you don't have this installed and it looks crap.

      • I had considered combining the keydown events in the directive into a single event, however because I need to return a value from there I decided to keep them separate.

      I'm fairly new to Angular2 so would of course appreciate your suggestions and feedback on any aspect of this implementation.







      share|improve this question













      I've tried to build a fairly simple, reusable and functional Angular2 autocomplete component.



      The component:





      import Component, Input, Output, OnInit, ContentChild, EventEmitter, HostListener from '@angular/core';
      import Observable from "rxjs/Observable";
      import AutoCompleteRefDirective from "./autocomplete.directive";

      @Component(
      selector: 'autocomplete',
      templateUrl: './autocomplete.component.html',
      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;




      The component HTML:





      <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>


      The component CSS:





      .autocomplete-wrapper 
      position: relative;


      .autocomplete
      position: absolute;
      z-index: 100;
      width: 100%;



      The directive:





      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:





      The highlight pipe:



      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>";
      )





      The implementation:



      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));




      A few thoughts:



      • The use of both a Component and a Directive isn't ideal but I couldn't figure out a better way to do it.

      • The getData property and search() functions have been separated so as to mimic a real life service call scenario. It took me an age working out how to wire this up using a property and =>! But is there a better way, especially when dealing with async calls?

      • The highlight pipe isn't necessary but it does improve the experience so I figured I'd include it here.

      • I'm leveraging the bootstrap list group in the component, so apologies if you don't have this installed and it looks crap.

      • I had considered combining the keydown events in the directive into a single event, however because I need to return a value from there I decided to keep them separate.

      I'm fairly new to Angular2 so would of course appreciate your suggestions and feedback on any aspect of this implementation.









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 14 at 23:42









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Jan 8 at 10:56









      James Law

      200128




      200128

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184569%2fangular-2-autocomplete%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184569%2fangular-2-autocomplete%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods