Modifying iframe src using click event from a separate component in Angular 10

I am looking to dynamically update the src attribute of an iframe when the menu bar is clicked. The menu bar resides in a separate component and includes a dropdown menu for changing languages. Depending on which language is selected, I want to update the src attribute of the iframe.

Below is the HTML code for my menu containing the 'updateSrc()' function:

<nav>

<div class="select-box">
                      <div class="select-box__current" tabindex="1">
                        <div class="select-box__value" (click)="updateSrc(first_url)">
                          <input class="select-box__input" type="radio" id="0" value="1" name="Ben" checked="checked"/>
                          <p class="select-box__input-text">Es</p>
                        </div>
                        <div class="select-box__value" (click)="updateSrc(second_url)">
                          <input class="select-box__input" type="radio" id="1" value="2" name="Ben"/>
                          <p class="select-box__input-text">En</p>
                        </div>
                        <div class="select-box__value">
                          <input class="select-box__input" type="radio" id="2" value="3" name="Ben"/>
                          <p class="select-box__input-text">It</p>
                        </div>
                        <img class="select-box__icon" src="http://cdn.onlinewebfonts.com/svg/img_295694.svg" alt="Arrow Icon" aria-hidden="true"/>
                      </div>

                      <ul class="select-box__list">
                        <li>
                          <label class="select-box__option" for="0" aria-hidden="aria-hidden">Es</label>
                        </li>
                        <li>
                          <label class="select-box__option" for="1" aria-hidden="aria-hidden">En</label>
                        </li>
                        <li>
                          <a href="https://esourcecapital.it/">
                          <label class="select-box__option" aria-hidden="aria-hidden">It</label>
                          </a>
                        </li>
                      </ul>
                    </div> 

</nav>

Here is the TypeScript file for handling the logic:

import { Component, OnInit } from '@angular/core';
import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browser';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {

  menu:boolean = false;

  constructor(private translate: TranslateService,
              private sanitizer: DomSanitizer)
    {  }

  ngOnInit(): void {

  }

  first_url = "https://www.youtube.com/embed/4oP20QZxahk";
  second_url = "https://www.youtube.com/embed/Q_ZPBqVF0_8";
  current_url: SafeUrl;

  updateSrc(url) {
    this.current_url=this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }


}

The iframe element that needs to be updated is located in a different component:


<div class="center">
                            <iframe width="640" height="360" id="frame" frameborder="0" src="https://www.youtube.com/embed/4oP20QZxahk" [src]="current_url" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<!--                            <div class="pairs">
                                <button md-button (click)="updateSrc(first_url)" id="first" class="top-link">Video en español</button>
                                <button md-button (click)="updateSrc(second_url)" id="second" class="top-link">Video in english</button>
                            </div> -->
                        </div>


In summary, the issue arises from having the menu and the iframe in separate components, making it challenging to update the iframe based on the language selection in the menu.

Answer №1

To facilitate data sharing between components, consider using a subject and a service:

Iframe Service

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class IFrameService {

  private srcSubject = new Subject<string>();

  srcObservable$: Observable<string> = this.srcSubject.asObservable();

  constructor() { 
  }

  changeSrc(incomingSrc) {
    this.srcSubject.next(incomingSrc);
  }
}

Next, inject the service into both the menu and iframe components:

Menu TS File

In the header component file, modify the `changeSrc` method to call the `IFrameService`'s `next` method to emit a new value for the created subject.

import { Component, OnInit } from '@angular/core';
import { DomSanitizer, SafeResourceUrl, SafeUrl } from '@angular/platform-browser';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {

  menu: boolean = false;

  constructor(private translate: TranslateService,
              private sanitizer: DomSanitizer,
              private iframeService: IFrameService)
    {  }

  ngOnInit(): void {

  }

  first_url = "https://www.youtube.com/embed/4oP20QZxahk";
  second_url = "https://www.youtube.com/embed/Q_ZPBqVF0_8";
  current_url: SafeUrl;

  updateSrc(url) {
      this.iframeService.changeSrc(this.sanitizer.bypassSecurityTrustResourceUrl(url));
  }
}

IFrame Component File

In the Iframe component file, create an instance of the service similar to the header file. Remember to instantiate it as a public service so you can use it in your template. Subscribe to the observable in your HTML using the async pipe.

<div class="center">
  <iframe width="640" height="360" id="frame" frameborder="0" src="https://www.youtube.com/embed/4oP20QZxahk" [src]="iframeService.srcObservable | async" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<!--<div class="pairs">
      <button md-button (click)="updateSrc(first_url)" id="first" class="top-link">Video en español</button>
      <button md-button (click)="updateSrc(second_url)" id="second" class="top-link">Video in english</button>
  </div> -->
</div>

If you're still unsure about implementing subjects and observables, check out this video for further clarification.

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

Issue encountered: Inoperable binding when employing ko.mapping with two distinct models

I've been struggling to implement a drop-down select in conjunction with a table on a page using knockout bindings. The issue arises when I try to use the mapping options in the knockout binding plugin – either the drop-down or the table behaves inc ...

Navigating through the complexities of managing asynchronous props and state in React-components

I'm really struggling to understand this concept. My current challenge involves passing asynchronously fetched data as props. The issue is that the props themselves are also asynchronous. Below is a simplified version of the component in question: i ...

What is the purpose of the Angular Material dashboard schematic boilerplate code?

After utilizing an Angular schematic, specifically ng generate @angular/material:dashboard, the generated code in the component.ts file looks like this: cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe( map(({ matches }) => { if (mat ...

Is it possible to return a promise within the .then function in AngularJS?

I have a unique service called "usersService". I want to create a special method that interacts with another custom service I built. This other service has two handy methods: getUser() and getCurrentUser(). The getCurrentUser() method relies on the injecte ...

What is the best method to retrieve the active element (the one that is currently focused) in Angular 6?

-- This is not a duplicate as the other questions are outdated. It is also different from the previous question! this.elm.nativeElement.ownerDocument.activeElement Furthermore, document.activeElement Returns the entire body element instead of just the ...

JavaScript Date displaying the string in the format YYYY/MM/DD HH:MM

I'm struggling to figure out how to format a date and time string like this: "YYYY-MM-DD-HH-MM" Can anyone help me with this? Here is the code I currently have: var x = new Date(); var formattedTimeStamp = x.toString(); Current Output: Tue Oct 3 ...

Why does jQuery only execute the very first condition or none at all if the first condition is false?

I'm trying to create a fixed button that, when clicked, scrolls to a specific section on the page. However, only the first condition seems to be working, and the other conditions are being ignored even when the first one is false. Can you help me figu ...

JavaScript onclick event on an image element

I have a JavaScript function that shows images using CSS styles. <script type="text/javascript"> $(function () { $("div[style]").click(function() { $("#full-wrap-new").css("background-image", $(this).css("background-image")); }); }); ...

What is the connection between @types, TypeScript, and Webpack?

When using an exported type in a .ts file, it is necessary to import it: import {jQuery} from 'jQuery' Even after adding the import, intellisense may not work until npm install @types\jQuery is executed. If @types are installed, intellis ...

I'm confused, I installed the module but it's still showing an error message saying it can

I've been working on coding a discord music bot, and here is the code I have so far: const config = require('config.json') const Discord = require('discord.js'); const ffmpeg = require('ffmpeg-extra') const client = new ...

Leveraging JQuery for activating an event with Bootstrap Scrollspy

I'm facing a challenge in capturing the Scrollspy event to execute a specific function. The Scrollspy feature is functioning correctly in terms of updating the active link on the navbar. However, I am struggling to capture the event for use in other p ...

Event vs ViewChild: Understanding the best way for parent components to obtain information from child

My situation involves multiple basic form components that need validation in the parent component. To achieve this, I must pass formGroups from the child components to the parent. The question is, what is the preferred method for passing a formGroup from a ...

Spirit.py navigates using javascript

Having trouble with Ghost.py. The website I'm trying to crawl uses javascript for paginated links instead of direct hrefs. When I click on the links, selectors are the same on each page so Ghost doesn't wait since the selector is already present. ...

Struggling to fetch a custom attribute from the HTML Option element, receiving [object Object] as the result instead

I've been facing a challenging issue all day. My task involves making an ajax call to a predefined JSON file and trying to save certain contents into option tags using custom attributes. However, every time I attempt to retrieve the data stored in the ...

Is Fetch executed before or after setState is executed?

I've encountered an issue while trying to send data from the frontend (using React) to the backend (Express) via an HTML form, and subsequently clearing the fields after submission. The code snippet below illustrates what I'm facing. In this scen ...

What is the best way to design an angular directive or service specifically for straightforward pagination featuring only next and previous options?

Within a block of div tags, an ng-repeat directive is being used to display sets of 3 divs at a time. By clicking on the next button, the next set of 3 divs should be displayed, and the same goes for the previous button. Check out the HTML code below: &l ...

Handling events with ReactJS can be made even more powerful by passing parameters to

Just dipping my toes into the world of ReactJs and I've put together a component to display a list of buses. My goal is to enable edit and delete functionality for each bus, but I'm struggling to pass the corresponding busId to my edit/delete met ...

What is the best way to display a custom row overlay in ag-grid?

I am looking to display a customized message when no users are found using ag-grid in Angular6. Below is the code snippet: ngOnInit() { this.gridOptions.frameworkComponents.loadingCellRenderer = TableLoadingComponent; this.rowBuffer = 0; this.rowSel ...

Leverage the power of function overloading in TypeScript for efficient code

How can function overloading be reused effectively in TypeScript? Consider a scenario where a function is overloaded: function apply(value: number): number; function apply(value: string): string; function apply(value: any): any { return value; } No ...

Issue with updating state following data retrieval in React hooks

Recently, I've been experimenting with an API and working on a React application for data display. However, I encountered an issue while setting the state using the setState method of React Hooks after sending my information through a form request via ...