81018

Angular - 404 (Not Found) when loading async data from endpoint

Question:

I keep getting an 404 error on my media player as the "sermon.fileName" property is made available after the component loads on screen. How can I work around this?

<a href="https://i.stack.imgur.com/DkTBW.png" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/DkTBW.png" data-original="https://i.stack.imgur.com/DkTBW.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

<strong>sermon.component.ts</strong>

import { Component, OnInit, ChangeDetectorRef, AfterViewChecked } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ApiProvider } from '../../providers/api/api'; import { Breakpoints, BreakpointState, BreakpointObserver } from '@angular/cdk/layout'; import { Observable } from 'rxjs'; import { environment } from '../../environments/environment'; import { SermonModule } from './sermon'; import { VgAPI } from 'videogular2/core'; @Component({ templateUrl: './sermon.component.html', providers: [ApiProvider] }) export class SermonComponent implements OnInit, AfterViewChecked { constructor(private apiProvider: ApiProvider, private route: ActivatedRoute, private breakpointObserver: BreakpointObserver, private cdRef: ChangeDetectorRef ) { } isMobile: Observable<BreakpointState>; public id: String; public sermon = {} as SermonModule.Sermon; api: VgAPI; ngOnInit() { this.id = this.route.snapshot.paramMap.get('id'); this.getSermon(this.id); this.isMobile = this.breakpointObserver.observe(Breakpoints.Handset); } ngAfterViewChecked() { this.cdRef.detectChanges(); } onPlayerReady(api: VgAPI) { this.api = api; this.api.getDefaultMedia().subscriptions.ended.subscribe( () => { this.api.getDefaultMedia().currentTime = 0; } ); } getSermon(id: String) { this.apiProvider.getSermon(id).subscribe((data: SermonModule.Sermon) => { if (environment.production === false) { console.log(data); console.log(new SermonObject().deserialize(data)); } this.sermon = new SermonObject().deserialize(data); }); } } class SermonObject implements SermonModule.Serializable<SermonModule.Sermon> { id: string; name: string; fileName: string; speaker: string; description: string; tags: string[]; date: string; sermonSession: string; deserialize(input) { this.id = input.id; this.name = input.name; this.fileName = input.fileName; this.speaker = input.speaker; this.description = input.description; this.tags = input.tags; this.date = input.date; this.sermonSession = input.sermonSession; return this; } }

<strong>sermon.component.html</strong>

<vg-player style="height: 50px;"> <vg-controls> <vg-play-pause></vg-play-pause> <vg-playback-button></vg-playback-button> <vg-time-display vgProperty="current" vgFormat="mm:ss"></vg-time-display> <vg-scrub-bar> <vg-scrub-bar-current-time></vg-scrub-bar-current-time> <vg-scrub-bar-buffering-time></vg-scrub-bar-buffering-time> </vg-scrub-bar> <vg-time-display vgProperty="left" vgFormat="mm:ss"></vg-time-display> <vg-time-display vgProperty="total" vgFormat="mm:ss"></vg-time-display> <vg-mute></vg-mute> <vg-fullscreen></vg-fullscreen> </vg-controls> <audio #media [vgMedia]="media" preload="auto"> <source [src]="sermon?.fileName" type="audio/mp3"> </audio> </vg-player>

<strong>api.provider.ts</strong>

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { environment } from '../../environments/environment'; import { map } from 'rxjs/operators'; @Injectable() export class ApiProvider { private apiUrl = environment.apiUrl; private bookUrl = 'assets/data/books.json'; private speakerUrl = 'assets/data/speakers.json'; constructor(private httpClient: HttpClient) { } public getAllSermons() { return this.httpClient.get(this.apiUrl + '/sermon').pipe(map((data: any) => data.data) ); } public getSermon(id: String) { return this.httpClient.get(this.apiUrl + '/sermon/' + id).pipe(map((data: any) => data.data) ); } public getAllBooks() { return this.httpClient.get(this.bookUrl).pipe(map((data: any) => data) ); } public getAllSpeakers() { return this.httpClient.get(this.speakerUrl).pipe(map((data: any) => data) ); } public getAllSessions() { return this.httpClient.get(this.apiUrl + '/sermon/session').pipe(map((data: any) => data.data) ); } }

Answer1:

You've got two options (or more). One would be to use a route resolver, to resolve the sermon before the component loads. Another would be to use an *ngif to only show the <audio> element if sermon is available:

<audio *ngIf="sermon" #media [vgMedia]="media" preload="auto"> <source [src]="sermon.fileName" type="audio/mp3"> </audio>

Recommend

  • Angular 7: ChangeDetectorRef detectChanges() causes infinite loop when called from inside a subscrip
  • Display different Vuejs components for mobile browsers
  • Getting the value from JSpinner (SWING)
  • Redirect website to mobile site and from mobile to desktop?
  • Fermi architecture possible solution to my comparative study?
  • ASPNetCore MVC Routing Let Server Handle Specific Route
  • Laravel 4 routing not working due to .htaccess file?
  • Iron Router: How do I send data to the layout?
  • Can I have a variable number of URI parameters or key-value pairs in Laravel 4?
  • Align navbar back button on right side
  • How to add date and time under each post in guestbook in google app engine
  • How to set/get protobuf's extension field in Go?
  • DirectX11 ClearRenderTargetViewback with transparent buffer?
  • Validaiting emails with Net.Mail MailAddress
  • sending/ receiving email in Java
  • Web-crawler for facebook in python
  • Akka Routing: Reply's send to router ends up as dead letters
  • AT Commands to Send SMS not working in Windows 8.1
  • Cannot Parse HTML Data Using Android / JSOUP
  • How to delete a row from a dynamic generate table using jquery?
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • json Serialization in asp
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • JTable with a ScrollPane misbehaving
  • Java static initializers and reflection
  • How to stop GridView from loading again when I press back button?
  • apache spark aggregate function using min value
  • unknown Exception android
  • Easiest way to encapsulate a HTML5 webpage into an android app?
  • Busy indicator not showing up in wpf window [duplicate]
  • Sorting a 2D array using the second column C++
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • failed to connect to specific WiFi in android programmatically
  • UserPrincipal.Current returns apppool on IIS
  • Unable to use reactive element in my shiny app
  • Conditional In-Line CSS for IE and Others?
  • java string with new operator and a literal
  • How can I use threading to 'tick' a timer to be accessed by other threads?