Component doing http call for Page not loading content properly


#1

I’ve pasted the code below. The deal is… I’m trying to asynchronously get some data from my API and load this component into my page once that data is retrieved. While it’s getting the data… the ‘loading’ in <song>loading...</song> is not displaying properly. I truly have no idea what I’m doing. I’ve been following the tutorials for Angular 2 to try to hack this project together. Any kind of feedback welcome!

home.html

<ion-navbar *navbar dark>
  <button menuToggle (click)="stopSong()">
    <ion-icon name="menu"></ion-icon>
  </button>
  <!-- <ion-title>k-bop!</ion-title> -->
</ion-navbar>

<ion-content class="home">
<ion-card>
    <song>Loading...</song>

    <ion-item>
      <button primary clear item-left>
        <ion-icon name="heart"></ion-icon>
        <div>12 Likes</div>
      </button>
      <button primary clear item-left>
        <ion-icon name="text"></ion-icon>
        <div>4 Comments</div>
      </button>
    </ion-item>
  </ion-card>

  <button full *ngIf="!loggedIn()" (click)="login()">Login</button>

</ion-content>

home.ts

import {Page, NavController} from 'ionic-framework/ionic';
import {LoginService} from '../../login.service';
import {SongService} from '../../song.service';
import {Song} from '../../song'
import {HTTP_PROVIDERS}    from 'angular2/http';
import {SongComponent} from '../../song.component';

@Page({
  templateUrl: 'build/pages/home/home.html',
  directives:[SongComponent],
  providers: [LoginService, HTTP_PROVIDERS, SongService]
})
export class HomePage {

  constructor(private _loginService: LoginService) { }

  loggedIn() {
    return this._loginService.loggedIn();
  }

  login() {
    this._loginService.login();
  }
}

song.component.ts

import {Component, OnInit} from 'angular2/core';
import {IONIC_DIRECTIVES} from 'ionic-framework/ionic';
import {Song}              from './song';
import {SongService}       from './song.service';
import {PlaylistService} from './playlist.service';

@Component({
  selector: 'song',
  template: `
  <div *ngIf="currentSong">
  <ion-item>
    <ion-avatar item-right>
      <ion-icon name="md-musical-note" item-right></ion-icon>
    </ion-avatar>
    <h2>{{ currentSong.artist }}</h2>
  </ion-item>

  <img [src]="currentSong.image_large" (click)="toggleSong()">

  <ion-card-content>
    <h4>{{ currentSong.title }}</h4>
  </ion-card-content>

  <ion-item class="deciders">
      <button dark clear round item-left (click)="decide(false)">
        <ion-icon name="sad"></ion-icon>
      </button>
      <button dark clear round item-right (click)="decide(true)">
        <ion-icon name="happy"></ion-icon>
      </button>
  </ion-item>
  </div>
  `,
  directives: [IONIC_DIRECTIVES]
  // styles: ['.error {color:red;}'],
})
export class SongComponent {
  songs: Song[];
  currentSong: Song;
  audio: any;
  paused: boolean;

  constructor (private _songService: SongService, private _playlistService: PlaylistService) {
    // this.currentSong = {artist: "Loading", title: "Loading Song", preview: "", image_large: "", spotify_url: ""};
    this.getSongs();
    console.log('calling api')
  }

  getSongs() {
    this._songService.getSongs()
       .subscribe(
         songs => { this.songs = songs; this.currentSong = this.songs[0]; console.log(this.currentSong)},
         error => console.log(<any>error));
  }

  toggleSong() {
    if (this.paused) {
      this.startSong();
      this.paused = false
    } else {
      this.stopSong();
      this.paused = true
    }
  }

  stopSong() {
    if (this.audio) {
      this.audio.pause();
    }
  }

  startSong() {
    if (this.audio) {
      this.audio.play();
    }
  }

  playSong() {
    return new Promise((resolve, reject) => {
      this.audio = new Audio(this.currentSong.preview);
      this.audio.autoplay = true;
      this.audio.onerror = reject;
      this.audio.onended = resolve;
    });
  }

  decide(choice) {
    if (choice) {
      this._playlistService.addSong(this.currentSong);
    }

    this.stopSong();
    let randomNumber = Math.round(Math.random() * (this.songs.length - 1));
    this.currentSong = this.songs[randomNumber];

    this.playSong().then((success) => {
      console.log("Preview complete")
    }, (error) => {
      alert("Something has gone wrong");
    });
  }
}

song.service.ts

import {Song} from './song';
import {SONGS} from './mock-songs';
import {Injectable} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import {Observable}     from 'rxjs/Observable';
import 'rxjs/Rx';

@Injectable()
export class SongService {
  private _songsUrl = "http://kbop.herokuapp.com/songs";
  // private _songsUrl = "app/songs"

  constructor(private http: Http) { }

  getSongs () {
    return this.http.get(this._songsUrl)
      .map(res => <Song[]> res.json())
      .do(data => console.log(data))
      .catch(this.handleError);
  }

  private handleError (error: Response) {
    // in a real world app, we may send the error to some remote logging infrastructure
    // instead of just logging it to the console
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
  }
}

song.ts

export interface Song {
  title: string;
  artist: string;
  preview: string;
  image_large: string;
  spotify_url: string;
}

#2

I just took the http part out unto a seperate plunkr and it is working

http://embed.plnkr.co/rzUaFA/