I want to change an iframe src when you click the menu bar. My menu bar is in another component, on which you are able to change the language in a dropdown menu. I want to change the iframe src depending on which language was clicked.
Here is my HTML menu wth a function named 'updateSrc()':
<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 my TS file:
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);
}
}
And also the iframe I want to change is in another component as I said before:
<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>
if everything were in the same component it would work, but the menu is in one component and the iframe tag in another.
CodePudding user response:
You can use a subject to share data between components. You need 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);
}
}
Than you'll inject the service in both components: menu and the iframe component
Menu TS File
At the header component file, you will change your changeSrc method, which will call the iFrame Service next method, that will emit the new value for the subject that you created.
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
At the Iframe component file, you will create a new instance of the service like you did for the header file, but you must instantiate it as a public service, so you will be able to use the service in your template. At your HTML you will subscribe to the observable 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 >
<button md-button (click)="updateSrc(first_url)" id="first" >Video en español</button>
<button md-button (click)="updateSrc(second_url)" id="second" >Video in english</button>
</div> -->
</div>
If you still have doubts of how to use subjects and the observable pattern, take a look at this video.