Amos
Amos

Reputation: 161

Runtime error - Cannot read property 'url' of undefined

I'm using ionic version 3 to develop my app, I'm using youtube REST API to fetch videos from my youtube playlist, however the video thumbnails are not displaying in my app and I get an error "Runtime error - Cannot read property 'url' of undefined"

Below is a specific line of code meant to get the video thumbnails and display them in the app:

<img [src]="list.snippet.thumbnails.standard.url">

The Rest of the code looks like this: media.html

<ion-header>
  <ion-navbar color="secondary">
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Media Gallery</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <ion-item>
    <ion-label stacked>Channel ID</ion-label>
    <ion-input type="text" [(ngModel)]="channelId"></ion-input>
  </ion-item>
  <button full ion-button (click)="searchPlaylists()" [disabled]="channelId === ''" color="primary">Search Playlists</button>

  <ion-list no-padding>
    <button ion-item *ngFor="let list of playlists | async" (click)="openPlaylist(list.id)">
      <ion-thumbnail item-start>
        <img [src]="list.snippet.thumbnails.standard.url">
    </ion-thumbnail>
    <h2>{{ list.snippet.title }}</h2>
    <p>{{ list.snippet.publishedAt | date:'short' }}</p>
    </button>
  </ion-list>
</ion-content>

media.ts

import { YtProvider } from './../../providers/yt/yt';
import { Component } from '@angular/core';
import { NavController, AlertController } from 'ionic-angular';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'page-media',
  templateUrl: 'media.html'
})
export class MediaPage {

  channelId = 'UCwsAikVrhBuJMIAfXB6SiqA'; // Devdactic Channel ID
  playlists: Observable<any[]>;

  constructor(public navCtrl: NavController, private ytProvider: YtProvider, private alertCtrl: AlertController) { }

  searchPlaylists() {
    this.playlists = this.ytProvider.getPlaylistsForChannel(this.channelId);
    this.playlists.subscribe(data => {
      console.log('playlists: ', data);
    }, err => {
      let alert = this.alertCtrl.create({
        title: 'Error',
        message: 'No Playlists found for that Channel ID',
        buttons: ['OK']
      });
      alert.present();
    })
  }

  openPlaylist(id) {
    this.navCtrl.push('PlaylistPage', { id: id });
  }
}

Below is more code playlist.ts

import { YtProvider } from './../../providers/yt/yt';
import { Observable } from 'rxjs/Observable';
import { Component } from '@angular/core';
import { NavController, NavParams, Platform } from 'ionic-angular';
import { YoutubeVideoPlayer } from '@ionic-native/youtube-video-player';


@Component({
  selector: 'page-playlist',
  templateUrl: 'playlist.html',
})
export class PlaylistPage {
  videos: Observable<any[]>;

  constructor(private navParams: NavParams, private ytProvider: YtProvider, private youtube: YoutubeVideoPlayer, private plt: Platform) {
    let listId = this.navParams.get('id');
    this.videos = this.ytProvider.getListVideos(listId);
  }

  openVideo(video) {
    if (this.plt.is('cordova')) {
      this.youtube.openVideo(video.snippet.resourceId.videoId);
    } else {
      window.open('https://www.youtube.com/watch?v=L658-04LHvQ&t=25s' + video.snippet.resourceId.videoId);
    }
  }
}

playlist.html

<ion-header>
    <ion-navbar color="secondary">
      <button ion-button menuToggle>
        <ion-icon name="menu"></ion-icon>
      </button>
      <ion-title>Recent Videos</ion-title>
    </ion-navbar>
  </ion-header>
<ion-content>
    <ion-list>
      <button ion-item *ngFor="let video of videos | async" (click)="openVideo(video)" detail-none>
        <ion-thumbnail item-start>
        <img [src]="video.snippet.thumbnails.standard.url">
      </ion-thumbnail>
      <h2>{{ video.snippet.title }}</h2>
      <p>{{ video.snippet.description }}</p>
      </button>
    </ion-list>
  </ion-content>

Display on the console:

etag
:
""_gJQceDMxJ8gP-8T2HLXUoURK8c/3XMZ7f8hgOqWSV9kp7zDUUp_xJk""
id
:
"PLXFzaYMJZXC8SVlwr_QktPPHhuyF2751M"
kind
:
"youtube#playlist"
snippet
:
channelId
:
"UCwsAikVrhBuJMIAfXB6SiqA"
channelTitle
:
"Amos Wambugu"
description
:
""
localized
:
{title: "KSSSA Games", description: ""}
publishedAt
:
"2018-02-20T15:26:30.000Z"
thumbnails
:
{default: {…}, medium: {…}, high: {…}, standard: {…}, maxres: {…}}
title
:
"KSSSA Games"
__proto__
:
Object
__proto__
:
Object
1
:
{kind: "youtube#playlist", etag: ""_gJQceDMxJ8gP-8T2HLXUoURK8c/XsEY4LCHcg2nXaAhhAkPqM1NxkI"", id: "PLXFzaYMJZXC_ooZUokrKDUIW1jmsfKAVY", snippet: {…}}
2
:
{kind: "youtube#playlist", etag: ""_gJQceDMxJ8gP-8T2HLXUoURK8c/cMgewOZqKa5imaBdXF3S_UsNm8Y"", id: "PLXFzaYMJZXC_8t4WTurPUZaINWUFfRwKQ", snippet: {…}}
3
:
{kind: "youtube#playlist", etag: ""_gJQceDMxJ8gP-8T2HLXUoURK8c/ksH2BayWOw44KODHKLbtEn9L3nM"", id: "PLXFzaYMJZXC8d1HLvOVDQNVNGaNss5IIY", snippet: {…}}
4
:
{kind: "youtube#playlist", etag: ""_gJQceDMxJ8gP-8T2HLXUoURK8c/c2ls-Or5pI4mXGMxY49UFYWye1w"", id: "PLXFzaYMJZXC8oxp6QTxAU2KWm27YlOzIl", snippet: {…}}
5
:
{kind: "youtube#playlist", etag: ""_gJQceDMxJ8gP-8T2HLXUoURK8c/uMlRzlJIxaeRaBCK9bEY8THsrm8"", id: "PLXFzaYMJZXC8ZYJSBKfx6yK9DT0XgdF2E", snippet: {…}}
length
:
6
__proto__
:
Array(0)


​

Upvotes: 0

Views: 1057

Answers (3)

Ishara Sandun
Ishara Sandun

Reputation: 737

Try this

<img [src]="list?.snippet?.thumbnails?.standard?.url">

You can use this to get rid of the exception.

Upvotes: 1

Erwin Rodriguez
Erwin Rodriguez

Reputation: 21

So when i have encountered this error it usually means that you are trying to use an object that hasn't been set yet. hence you are trying to use a property of undefined. basically

<img [src]="list.snippet.thumbnails.standard.url">

is being run before you get the http request back from the server and set the list object.

my solution to this was to wrap the http call inside an ionViewCanEnter() function. and only resolve and enter the view AFTER the http call is returned and the object is set.

ionViewCanEnter() {
  return new Promise((resolve, reject) => {
    var reobj = {'complete':true};
      this.returnStyleInfo('http', 'mcfarland').subscribe((data) => {
        this.styles = data;
        resolve(reobj);
      });
    });
}

and the function called returnStyleInfo() is simply a http get request.

returnStyleInfo(urlprefix, datasource): Observable<any>{
  return this.http.get(urlprefix+'://demoapp.iescentral.com/appJson/read/'+datasource+'?format=json')
}

and also remember to import 'observable' at the top of your page

import {Observable} from 'rxjs/Observable';

Upvotes: 0

Toby Okeke
Toby Okeke

Reputation: 654

This means that property isn't contained in the response from your request. Cross-check the json data and ensure you are parsing it properly

Upvotes: 0

Related Questions