Reputation: 747
Can't understand why the data not binding on ui, trying to bind array using *ngFor, but nothing is display on ui while the data is exist in array. Here the component code:
import { Component, Injector, OnInit, OnDestroy, Pipe } from '@angular/core'
import { AdvancedPostsService } from '../../services/advanced.posts.service'
import { SpinnerService } from '../../services/spinner.service'
import { PathKey } from '../../helpers/platform.helpers'
import { Router } from '@angular/router'
import { ToolsService } from '../../services/tools.service'
import { YoutubeToolsService } from '../../services/youtube.tools.service'
@Pipe({ name: 'safe' })
@Component({
selector: 'advanced-post-youtube-step-component',
templateUrl: '../../templates/advanced-posts-templates/advanced.post.youtube.component.html'
})
export class AdvancedPostYoutubeStep implements OnInit, OnDestroy {
private postId: number;
private stepId: number;
private postType: number;
videoList: any[] = [];
private youTubeWatchUrl = "https://www.youtube.com/embed/";
i = 0;
constructor(private advancedPostsService: AdvancedPostsService,
private spinner: SpinnerService,
private toolsService: ToolsService,
private injector: Injector,
private router: Router,
private youtubeToolsService: YoutubeToolsService) {
this.injectParentData();
}
ngOnInit(): void {
this.youtubeToolsService.change.on(this.onYoutubeVideosLoaded.bind(this));
this.youtubeToolsService.initGoogleAuthentication();
this.spinner.stop();
}
onYoutubeVideosLoaded(self: YoutubeToolsService) {
for (let item of self.videoList) {
if (item) {
console.log(item);
this.videoList.push({
id: item.snippet.resourceId.videoId,
url: this.youTubeWatchUrl + item.snippet.resourceId.videoId
});
}
}
console.log(this.videoList);
}
ngOnDestroy(): void {
this.youtubeToolsService.change.off(this.onYoutubeVideosLoaded.bind(this));
this.spinner.start();
}
injectParentData() {
this.postId = this.injector.get(PathKey.PostId);
this.stepId = this.injector.get(PathKey.StepId);
this.postType = this.injector.get(PathKey.PostType);
}
}
And ui part:
<div class="col-md-6 col-md-offset-3">
<h3 class="text-center">Select video</h3>
<div>
<iframe *ngFor="let video of videoList" type="text/html" class="video-responsive" [src]="video?.url | safe" frameborder="0"></iframe>
</div>
<h4>{{videoList.length}}</h4>
</div>
Even videoList.lenth
do not displayed. Anyone know what the problem here?
UPDATE YoutubeToolsService code:
import { NgZone, Injectable} from '@angular/core'
import { OperationDataResult } from '../helpers/operation.models'
import { Config } from '../helpers/social.models'
import { LiteEvent } from '../helpers/lite.event'
import { SocialService } from '../services/social.service'
declare var gapi: any;
@Injectable()
export class YoutubeToolsService {
private loginStatus: any;
private onChange = new LiteEvent<YoutubeToolsService>();
get change() { return this.onChange.expose(); }
videoList: any[] = [];
requestVideoPlaylist(playlistId) {
var requestOptions = {
playlistId: playlistId,
part: 'snippet',
maxResults: 10
};
var request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(response => {
var playlistItems = response.result.items;
if (playlistItems) {
this.videoList = playlistItems;
this.onChange.trigger(this);
}
});
}
Upvotes: 1
Views: 142
Reputation: 136174
Basically you are updating view binding variable from outside Angular context. In that case zonejs doesn't understand binding got updated and won't able to perform change detection. That's why in this case you've to run Change Detection cycle your self inside onYoutubeVideosLoaded
function. For the same you could use ChangeDetectorRef
API & call detectChanges
method whenever you want to run Change Detection to update binding manually.
constructor(private ref: ChangeDetectorRef) { }; //inject & import ChangeDetectorRef
//OR
//constructor(private _ngZone: NgZone) { }; //make sure constructor have NgZone
onYoutubeVideosLoaded(self: YoutubeToolsService) {
//below commented that can be alternative way of doing it
//this._ngZone.run(() => {
for (let item of self.videoList) {
if (item) {
console.log(item);
this.videoList.push({
id: item.snippet.resourceId.videoId,
url: this.youTubeWatchUrl + item.snippet.resourceId.videoId
});
}
}
//running CD manually
this.ref.detectChanges();
//});
}
Upvotes: 2