Ionic2 Rest Service access and data binding


#1

Hi All,

I am trying to get my Ionic2 app to do a GET call to a RESTful service. When I hard-code the Json data, it works perfectly, however when I make a call to the service, the result is null.

I built the app using the CLI:

$ ionic start jobs-4hire sidemenu --v2


I am trying to call the following service:


However, I get the following null result when my Ionic2 app calls the same service:


When I switch it to rather call the hard-coded data, it works:


The CLI console has no errors:


Please can anyone advise what I am doing incorrectly? My source code is below.

Thank you

page1.html

page1.ts


Here is the same code in text:

page1.html

<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Search</ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding class="page1">
  <ionic-content>
      <label class="item item-input">
        <i class="icon ion-search placeholder-icon"></i>
        <input type="search" placeholder="Search">
      </label>
      <ionic-list>
        <ionic-item *ngFor="#result of results">
<!--          <ion-thumbnail item-left><img [src]="result.avatar"></ion-thumbnail> -->  
          <h3>{{result.firstName}}</h3>
<!--          <p>{{result.subCategoryAsString}}</p>
          <icon item-right [name]="result.averageRating==='4' ? 'musical-tones' : 'film'"></icon>
              <icon item-right person [hidden]="result.averageRating===null 'song'"></icon> -->
        </ionic-item>
      </ionic-list>
  </ionic-content>
</ion-content>

page1.ts

import { Component } from '@angular/core';
import { NavController, Alert } from 'ionic-angular';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Component({
  templateUrl: 'build/pages/page1/page1.html'
})
export class Page1 {
  private nav:NavController = null;
  private http:Http = null;
  private results:any = null;
  private alert:Alert = null;
  private posts:any = null;
  constructor(nav:NavController, httpService:Http) {
    this.nav = nav;
    this.http = httpService;
    this.results = this.getHardCodedResults();
    //this.results = this.getResults();
    console.log('>>>>>>>>>>>>>>>>>>>>> \n'+this.results);
  }
  KeyHasBeenPressed(e) {
    if (e.keyIdentifier === 'Enter') {
      this.http.get('http://localhost:8080/www/employee/list').subscribe((response) => {
        this.results = response.json().results;
      });
    }
  }
  getResults() {
    var result = null;
    this.http.get('http://localhost:8080/www/employee/list').subscribe((response) => {
      result = response.json().results;
    });
    return this.posts;
  }
  getHardCodedResults() {
    return [{"id":1,"username":"RICHARD","password":"password","firstName":"Richardx","lastName":"Marais","phoneNumber":"0768454060","mobileNumber":"0768454060","emailAddress":"richard_marais@hotmail.com","averageRating":4,"salary":400,"salaryTimeframe":1,"sex":1,"jobTitle":"Gardiner","jobDescription":"I work all sorts of gardining work.","jobDetails":"I am fluent in English and Afrikaans","range":30,"driversLicence":1,"workLong1":"28.85","workLat1":"-25.766667","workLong2":null,"workLat2":null,"workLong3":null,"workLat3":null,"workLong4":null,"workLat4":null,"workLong5":null,"workLat5":null,"avatar":null,"lastAccessDateAsString":"04/07/2016 12:24:19","joiningDateAsString":"04/07/2016 12:24:19","subCategoryAsString":"Gardner","categoryAsString":"Domestic"}];
  }
}

app.ts

import { Component, ViewChild } from '@angular/core';
import { App, ionicBootstrap, Platform, Nav } from 'ionic-angular';
import { StatusBar } from 'ionic-native';
import { HTTP_PROVIDERS } from '@angular/http';
import { Page1 } from './pages/page1/page1';
import { Page2 } from './pages/page2/page2';
@Component({
  templateUrl: 'build/app.html',
  providers: [HTTP_PROVIDERS]
})
class MyApp {
  @ViewChild(Nav) nav: Nav;
  rootPage: any = Page1;
  pages: Array<{title: string, component: any}>
  constructor(private platform: Platform) {
    this.initializeApp();
    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Page uno', component: Page1 },
      { title: 'Page dos', component: Page2 }
    ];
  }
  initializeApp() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
    });
  }
  openPage(page) {
    // Reset the content nav to have just this page
    // we wouldn't want the back button to show in this scenario
    this.nav.setRoot(page.component);
  }
}
ionicBootstrap(MyApp);


How to fetch json from the response
#2

getResults returns this.posts, which I never see being assigned to. That being said, an important heuristic when dealing with futures (Promises or Observables): if you call a function that returns one, in most circumstances, you should also return one. Virtually never should you be returning a concrete object. You have so many anys and functions without return types that it’s hard to tell what things are supposed to be, which makes your code (a) hard to read and (b) prone to bugs. I’m assuming Page1.results is supposed to be an array of something. If that’s the case, you cannot expect getResults to return that array. Not going to happen. That’s not how futures work. Assign to it in the subscribe handler and let Angular’s change detection do its job, do NOT assign that to a local variable as you are currently doing. That will never do what you want it to. Your console log at the end of the constructor is useless.


#3

Hi rapropos,

Thank you for your advise. I am still very new to Ionic/Angular so don’t really know what I am doing yet.

I see that this.posts is never being assigned to. I have changed that now, but I get undefinedl returned from the service call.


I don’t 100% understand all your points yet, but will try digest and implement the changes you suggest. I would appreciate it if you could give some code examples if possible?


What type should this.results be?

private results:<???> = null;

Is the getResults() function correct now? I think it is returning an Observable? But it is undefined.


I appreciate your help.


#4

FIXED!

The problem was with my server. It was not allowing Cross-Origin access.

My Server is written in Java, with Spring. Adding the CrossOrigin annotation fixed.

@CrossOrigin(allowedHeaders = {"*"})
@RestController
@RequestMapping(EmployeeRESTService.BASE_URI)
public class EmployeeRESTService {