1

I'm new to IONIC/Angular and Javascript but gome some background in other languages. The problem that I am facing is that I am getting JSON data from external API (I've created API with Strapi) and I'm getting the responses but can't get them displayed on Views

Here is my code enter image description here vowels.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
 
// Typescript custom enum for search types (optional)
export enum SearchType {
  all = '',
  vowels = 'vowel',
  easy = 'easy',
  hard = 'hard',
  naglos = 'naglos',
  wyglos = 'wyglos',
  srodglos = 'srodglos'
}

// Typescript custom enum for search types (optional)
export enum Categories {
  all = '',
  naglos = 'naglos',
  wyglos = 'wyglos',
  srodglos = 'srodglos'
}
 
@Injectable({
  providedIn: 'root'
})
export class VowelService {
  url = 'http://localhost:1337/vowels';
 
  /**
   * Constructor of the Service with Dependency Injection
   * @param http The standard Angular HttpClient to make requests
   */
  constructor(private http: HttpClient) { }
 
  /**
  * Get data from the local API 
  * map the result to return only the results that we need
  * 
  * @param {string} title Search Term
  * @param {string} vowelType
  * @param {Categories} categories easy, hard, 
  * @returns Observable with the search results
  */
  searchData(title: string): Observable<any> {
    return this.http.get(`${this.url}?name=${encodeURI(title)}`).pipe(
      map(results => results['Search'])
    );
  }

  /* GET only Vowels that has category equal to = 
  */

  searchVowel(type: Categories): Observable<any> {
  return this.http.get(`${this.url}?&categories.name=${type}`).pipe(
    map(results => results['Search'])
  );
}
 
  /**
  * Get the detailed information for an ID using the "i" parameter
  * 
  * @param {string} id imdbID to retrieve information
  * @returns Observable with detailed information
  */
  getDetails(id) {
    return this.http.get(`${this.url}?i=${id}&plot=full`);
  }
}

vowels.page.html

<ion-header>
  <ion-toolbar color="primary">
    <ion-title>Wyszukiwarka samogłosek</ion-title>
  </ion-toolbar>
</ion-header>
 
<ion-content>
 
  <ion-searchbar [(ngModel)]="searchTerm" (ionChange)="searchChanged($event)"></ion-searchbar>
 
  <ion-item>
    <ion-label>Wybierz typ</ion-label>
    <ion-select [(ngModel)]="type" (ionChange)="searchChangedVowels($event)">
      <ion-select-option value="">Wszystkie</ion-select-option>
      <ion-select-option value="naglos">Nagłos</ion-select-option>
      <ion-select-option value="srodglos">Śródgłos</ion-select-option>
      <ion-select-option value="wyglos">Wygłos</ion-select-option>
    </ion-select>
  </ion-item>
 
  <ion-list>
 
    <ion-item button *ngFor="let item of (results | async)" [routerLink]="['/', 'vowels', item.id]">

 
      <ion-label text-wrap>
        <h3>{{ item.id }}</h3>
        <h3>{{ item.name }}</h3>
      </ion-label>
 
 
    </ion-item>
 
  </ion-list>
 
</ion-content>

vowels.page.ts

import { VowelService, Categories } from './../../services/vowels.service';
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
 
@Component({
  selector: 'app-vowels',
  templateUrl: './vowels.page.html',
  styleUrls: ['./vowels.page.scss'],
})
export class VowelsPage implements OnInit {
 
  results: Observable<any>;
  searchTerm: string = '';
  type: Categories = Categories.all;
 
  /**
   * Constructor of our first page
   * @param vowelService The movie Service to get data
   */
  constructor(private vowelService: VowelService) { }
 
  ngOnInit() { }
 
  searchChanged() {
    // Call our service function which returns an Observable
    this.results = this.vowelService.searchData(this.searchTerm);
  }

  searchChangedVowels() {
    // Call our service function which returns an Observable
    this.results = this.vowelService.searchVowel(this.type);
    
  }
}

1 Answer 1

1

You don't get the display the data in your page as the map operator consumed the observable.
You shold use it in your service file as:

pipe(map(results => {
    return results["search"]
  }))

This way your function will be returning an Observable.
You should also change the method in your vowels.page.ts as something like:

//Results are type of object or any in my example
results: any || yourDataModelType ;  
this.vowelService.searchData(this.searchTerm).subscribe(results => {
    this.results = results;
})

With this way you have generated an Observable and consumed in your page when you get the data from your server.

Note that you will only get the results when the observable is indeed returned a data that can be consumed.

Another note that when you subscribed to an observable, you should unsubscribe when you are done with it for memory leak purposes. In Ionic/Angular, you can do it inside an ngOnDestroy() cycle. with something like:

//Define a subscription variable in your page.ts   
sub: Subscription  

//Assign it inside your function
this sub =  this.vowelService.searchData(this.searchTerm).subscribe(results => {
    this.results = results;  
})
 
//Define OnDestroy Cycle for the page
export class VowelsPage implements OnInit, OnDestroy

//Add ngOnDestroy cycle and unsubscribe inside.
ngOnDestroy(){  
    if(this.sub){sub.unsubscribe()}
}

I suggest you to have a deeper look on the RxJs library and check Observable type for better understanding. https://www.learnrxjs.io/

Sign up to request clarification or add additional context in comments.

1 Comment

Well I've tried this but the problem is I'm getting "undefined" instead of JSON/Obvervable - added console.log(results) and it is returning me undefined Any idea what is wrong?

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.