Rebuilding a feature in response to changing data

There are numerous answers to my question, but I am struggling to understand what steps I should take.

Currently, I have a child component that is generated when a play button in another child component is clicked. This process occurs through a service that shares the data with the parent component. The parent then passes this data and creates my audio player child component. The issue I am facing is that if the user navigates to another page and attempts to play audio there, the old audio continues to play while the new audio does not start.

I am wondering if there is a specific lifecycle hook or method that I can use to destroy the old audio component and create a new one when clicked?

Info Box - Initial activation upon clicking the play button.

export class InfoBoxComponent implements OnInit {
  ...

  activateAudioPlayer(session) {
    this.newAudioService.newAudio(session)
  }
}

New Audio Service

export class NewAudioService {
  newActiveAudioSource: Subject<string> = new Subject<string>();

  newAudio(session) {
    this.newActiveAudioSource.next(session);
  }

  newActiveAudio$ = this.newActiveAudioSource.asObservable();
}

Frontend Component - Parent Component of Info Box and Audio Player

@Component({ 
   template: `<audio-player *ngIf='newActiveAudio' [newActiveAudio]='newActiveAudio'></audio-player>`,
})

export class FrontendComponent implements OnInit {

  ...

  ngOnInit() {
    this.sub = this.newAudioService.newActiveAudio$.subscribe(
      newActiveAudio => {
        this.newActiveAudio = newActiveAudio;
      });
  }

  ngOnDestroy() {
    // prevent memory leak when component destroyed
    this.sub.unsubscribe();
  }
}

Answer №1

Enhance your Angular application with this custom directive that updates the view when the key value is modified:

import {
  Directive,
  EmbeddedViewRef,
  Input,
  OnChanges,
  SimpleChanges,
  TemplateRef,
  ViewContainerRef
} from '@angular/core';

@Directive({
  selector: '[wRecreateViewKey]'
})
export class UpdateViewDirective implements OnChanges {
  @Input('wRecreateViewKey') key: any;

  viewRef: EmbeddedViewRef<any>;

  constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.key) {
      if (this.viewRef) {
        this.clearView();
      }

      this.createView();
    }
  }

  private createView() {
    this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
  }

  private clearView() {
    this.viewRef.destroy();
    this.viewRef = null;
  }
}

Example of how to use this directive:

<!-- `custom-component` will refresh whenever there are changes in `value`. -->

<custom-component *wRecreateViewKey="value"></custom-component>

<!-- The directive can also be applied to regular HTML elements or containers -->
<div *wRecreateViewKey="value"></div>
<ng-container *wRecreateViewKey="value"></ng-container>

Answer №2

Discovered a nifty workaround for this issue. Place your element within an array and utilize ngFor with trackBy

<content *ngFor="let item of [myItem]; trackBy: trackByItemProp">
        </content>

Answer №3

To achieve this, one approach is to first set isActiveAudio = false, then use Angular to update the interface by using setTimeout(), and finally assign a new value to isActiveAudio:

this.subscription = this.audioService.isActiveAudio$.subscribe(isActiveAudio => {
    this.isActiveAudio = false;
    setTimeout(() => {
        this.isActiveAudio = isActiveAudio;
    });
});

Answer №4

Make sure to set newAudioService as null and then utilize ChangeDetectorRef.detectChanges() to trigger a screen update, resulting in the destruction of the component. Afterwards, it is important to reconfigure newActiveAudio and regenerate the component.

html

<audio-player *ngIf='newActiveAudio' [newActiveAudio]='newActiveAudio'></audio-player>

TS

constructor(private changeDetectorRef: ChangeDetectorRef) {
}
    
ngOnInit() {
    this.sub = this.newAudioService.newActiveAudio$.subscribe(
        newActiveAudio => {
            this.newActiveAudio = null;
            this.changeDetectorRef.detectChanges();
            this.newActiveAudio = newActiveAudio;
        }
    );
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The TypeScript compiler is unable to locate the identifier 'Symbol' during compilation

Upon attempting to compile a ts file, I encountered the following error: node_modules/@types/node/util.d.ts(121,88): error TS2304: Cannot find name 'Symbol'. After some research, I found that this issue could be related to incorrect target or l ...

When the button is clicked, I desire to reveal the background color of a specific div

<div class="mat-list-item" *ngIf="authService.isAdmin()" (click)="openModal('site-settings', site.siteID)"> <span class="mat-list-item-content">{{ "Application.site_settings_label&q ...

Having difficulties in TypeScript identifying types within a project containing multiple node_modules directories

I am currently in the process of transitioning a codebase from Flow to TypeScript. I am encountering an issue with the error message Cannot find module 'SOME DEPENDENCY' or its corresponding type declarations.ts(2307) for several dependencies tha ...

Display an error message in the input type file Form Control if the file format is not .doc or .docx

I need a way to display an alert if the user tries to submit a file that is not of type doc or docx. I've implemented a validator for this purpose and would like the alert message (Unacceptable file type) to be shown when the validation fails. Here i ...

Angular has a way of causing confusion when it comes to differentiating between anchor scrolling and wildcard routing, denoted by

I am facing an issue in my Angular project where anchor scrolling is conflicting with wildcard routes. Here is what I have done in the project: I have enabled anchor scrolling in my app.module.ts like this: RouterModule.forRoot( [ { path: &ap ...

Cypress: Unable to properly stub API with cy.intercept()

Whenever I utilize the cy.intercept() function, the API fails to stub. cy.intercept("GET", `${API}farm/list`, { body: { statusCode: 200, message: "Request successful", result: seededFarmList, }, }); The way I import the fixture file is as ...

What steps can I take to ensure that the Kendo Drawer remains open when clicked? (Using Angular with Kendo UI)

My goal is to prevent the drawer from shrinking when displayed on a desktop-sized screen. Currently, I am utilizing @HostListener to detect window resizes and update values accordingly. However, whenever I click on a drawer item, the menu collapses which ...

Requesting Next Page via Angular GET Method for Paginated API

Having trouble loading data from a paginated REST API using the code below. Any suggestions for a better approach are welcome! component.ts import { Component, OnInit } from '@angular/core'; import {HttpClient} from '@angular/common/http&a ...

Bug with opening modals in Angular 9 using ngx-bootstrap

Greetings everyone, I am facing an issue while trying to utilize modal in angular with ngx bootstrap. The modal is housed in a separate component and I am using a subject to trigger an event to open it. The problem at hand: Upon clicking the button to o ...

Share edited collection with Observer

The challenge Imagine creating an Angular service that needs to expose an Observable<number[]> to consumers: numbers: Observable<number[]>; Our requirements are: Receive the latest value upon subscription Receive the entire array every tim ...

Using Angular 2 for Applet Integration

I am currently facing an issue with embedding my Applet .jar file into my Angular 2 Project. Many solutions suggest using the <applet></applet> tag, but I encounter the following error when attempting to do so: Unhandled Promise rejection: Te ...

Collaborating ASP.NET MVC and WebAPI token sharing

Within my ASP.NET MVC and Angular2 application, I rely on Identity Server 3 for user authentication. The usual process involves users logging into the MVC application, which then saves the token in a cookie. Once logged in successfully, users can perform ...

Order Typescript by Segment / Category

Suppose we start with this original array of objects: {vendor:"vendor1", item:"item1", price:1100, rank:0}, {vendor:"vendor1", item:"item2",price:3200, rank:0}, {vendor:"vendor1", item:"item3", price:1100, rank:0}, {vendor:"vendor2", item:"item1", price: ...

Implementing flexible number of generic arguments in Typescript for React components

When working with ReactJS and TypeScript, I found a clever way to conditionally render components based on the truthiness of a given property. Here is an example implementation: // Defining a type helper for Maybe export type Maybe<T> = T | undefined ...

Updating the array in React state does not work properly

Update: Visit the Snack Expo for the latest version. I have a page that displays a list. When I click on a Delete button, my goal is to remove the item with a specific id from the list. The code snippet is shown below: import { useState, memo, useCallbac ...

Customizing Tabs in Material UI v5 - Give your Tabs a unique look

I am attempting to customize the MuiTabs style by targeting the flexContainer element (.MuiTabs-flexContainer). Could someone please clarify the significance of these ".css-heg063" prefixes in front of the selector? I never noticed them before upgrading my ...

Utilizing mapped types in a proxy solution

As I was going through the TS Handbook, I stumbled upon mapped types where there's a code snippet demonstrating how to wrap an object property into a proxy. type Proxy<T> = { get(): T; set(value: T): void; } type Proxify<T> = { ...

Cypress automation script fails to trigger Knockout computed subscription

Within my setup, I have implemented two textboxes and a span to display the result. Date: <input data-bind="value: dateValue"/> Number: <input data-bind="value: dateValue"/> Result : <span data-bind="text: calculatedValue">Result Should ...

Error in React 16.3 Context: The anticipated input for built-in components should be a string, while for composite components it should be a class or function. However, an

I am fairly new to React, so this issue may be quite simple. Essentially, I have been attempting to utilize modals with Context. I have set up my Context in a separate file: import { createContext } from 'react'; export const ModalContext = cr ...

What steps can I take to fix the Error: Module not found "." in Ionic 3?

While working on building an ionic project for production, everything runs smoothly in debug mode. However, when I try to serve it, no errors appear. But when attempting to build or run android, two different errors are thrown. Despite checking in IDEs lik ...