1

I am making some application for Marvel API

https://developer.marvel.com/

The request is that i need to have search input and when user search some value to show him results from Marvel API, only problem is that i dont want button and call click to go to API and return results. It must return results when user type inside input. I know how to make it when i have button, but can someone help me to make it when user just type inside input. This is what i have for now when simple button exist

app,module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { Ng2SearchPipeModule } from 'ng2-search-filter';
import { Ng2OrderModule } from 'ng2-order-pipe';
import { Md5 } from 'ts-md5/dist/md5';
import { CharactersService } from './characters/characters.service';
import { NgxPaginationModule } from 'ngx-pagination';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { CharactersListComponent } from './characters/characters-list/characters-list.component';

@NgModule({
    declarations: [
        AppComponent,
        CharactersListComponent
    ],
    imports: [
        BrowserModule,
        FormsModule,
        HttpClientModule,
        AppRoutingModule,
        Ng2SearchPipeModule,
        Ng2OrderModule,
        NgxPaginationModule,
    ],
    providers: [CharactersService, Md5],
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
    bootstrap: [AppComponent]
})
export class AppModule { }

characters.service.ts

import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Md5 } from 'ts-md5/dist/md5';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

@Injectable()
export class CharactersService {
    private _marvelCharacterUrl: string = "https://gateway.marvel.com:443/v1/public/characters";
    private _publicKey: string = "c4b5296bc35888971631d22848916410";
    private _privateKey: string = "fddd97e16368b2fee706a1f6de69f30f191467d3";
    constructor(private _httpService: HttpClient, private _md5: Md5) { }
    private getHash(timeStamp: string): string {
        let hashGenerator: Md5 = new Md5();
        hashGenerator.appendStr(timeStamp);
        hashGenerator.appendStr(this._privateKey);
        hashGenerator.appendStr(this._publicKey);
        let hash: string = hashGenerator.end().toString();
        return hash;
    }
    private getTimeStamp(): string {
        return new Date().valueOf().toString();
    }    
    getAllCharacters() {
        let timeStamp = this.getTimeStamp();
        let hash = this.getHash(timeStamp);
        let requestUrl = this._marvelCharacterUrl + "?orderBy=name" + "&ts=" + timeStamp + "&apikey=" + this._publicKey + "&hash=" + hash;
        return this._httpService.get(requestUrl);
    }

    getCharacterByName(name: string) {
        let timeStamp = this.getTimeStamp();
        let hash = this.getHash(timeStamp);
        let requestUrl = this._marvelCharacterUrl + "?orderBy=name" + "&nameStartsWith=" + name + "&ts=" + timeStamp + "&apikey=" + this._publicKey + "&hash=" + hash;
        return this._httpService.get(requestUrl);
    }

}

characters-list.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { CharactersService } from '../characters.service';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
    selector: 'app-characters-list',
    templateUrl: './characters-list.component.html',
    styleUrls: ['./characters-list.component.css']
})
export class CharactersListComponent implements OnInit {
    private characters: any = [];

    constructor(private charactersService: CharactersService, private router: Router,
        private activatedRoute: ActivatedRoute ) { }

ngOnInit() {
    this.getCharacters();
}

private getCharacters(){
    this.charactersService.getAllCharacters()
        .subscribe(characters => {
            this.characters = characters;    
        });
}
    private getCharactersSearch(query: string) {
        this.charactersService.getCharacterByName(query)
            .subscribe(characters => {
                this.characters = characters;
            });
    }
}

characters-list.component.html

<header>
  <nav class="navbar navbar-default">
    <a class="navbar-brand" href="#">Application</a>
  </nav>
</header>

<div class="container">
  <div class="row">
    <nav class="navbar">
      <input class="form-control" type="text" name="search" #searchTerm>
      <button (click)="getCharactersSearch(searchTerm.value)">Search</button>
    </nav>
    <table class="table">
      <thead>
        <tr>
          <th>#</th>
          <th>Name
          </th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let character of characters.data.results | orderBy: key : reverse | paginate: { itemsPerPage: 10, currentPage: p }">
          <td>{{character.id}}</td>
          <td>{{character.name}}</td>
        </tr>
      </tbody>
      <pagination-controls (pageChange)="p = $event"></pagination-controls>
    </table>
  </div>
</div>

3 Answers 3

3

Use keyup on input (keyup)="getCharactersSearch(searchTerm.value)",

<nav class="navbar">
    <input class="form-control" type="text" name="search" #searchTerm  (keyup)="getCharactersSearch(searchTerm.value)">
</nav>

This will call api when ever user start typing

Here are the official docs

Update:

<nav class="navbar">
    <input class="form-control" type="text" name="search" #searchTerm  (keyup)="searchTerm.value.length ? getCharactersSearch(searchTerm.value) : getCharacters()">
</nav>
Sign up to request clarification or add additional context in comments.

2 Comments

The problem is here that on NgInit i already have some initial results from api, i need also when inout is empty that results are back, please take a look at characters-list.component.ts
Can you pleasehelp me with this also, txanks stackoverflow.com/questions/48403243/…
0

Here is the better way to go , why this is better , please read comment:

Template Side :

<input #search type="text" name="search" />

Component side :

@ViewChild('search') search: ElementRef;
ngOnInit() {
    let inputElm = this.search.nativeElement;
    /**
    * Observable.fromEvent :
    * To prevent call on each keyup event , this will wait for 200ms while user 
    * will be typing , just to reduce load over server and to reduce api calls
    */
    Observable.fromEvent(inputElm, 'keyup').debounceTime(200).subscribe(res => {
        if (inputElm.value.length > 0) {
            console.log(inputElm.value);
        } else {
            console.log('Empty');
        }
    });
}

WORKING DEMO

Comments

0

Why don't you use autocomplete.

Doc for autocomplete

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.