My app works perfectly if I copy exactly the built-in function from Twitter docs (https://dev.twitter.com/web/javascript/loading) into ngAfterViewInit function, but when I switch the route, the widget disappears also.
Here is the code to work only for the first page load:
import { Component, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute, ParamMap, Params } from '@angular/router';
import { Observable, Subscription } from 'rxjs/Rx';
export class ProjectDetailComponent implements OnInit, OnDestroy, AfterViewInit {
constructor(
private route: ActivatedRoute,
private router: Router
) { }
ngOnInit(){}
ngAfterViewInit(){
(<any>window).twttr = (function(d, s, id) {
let js, fjs = d.getElementsByTagName(s)[0],
t = (<any>window).twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = 'https://platform.twitter.com/widgets.js';
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, 'script', 'twitter-wjs'));
}
}
Then I found an accepted solution from this (Twitter widget on Angular 2), but the widget is not even shown from the first load and no errors so I don't even know where I was wrong.
Here is the code that never shows up Twitter widget without any error:
import { Component, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute, ParamMap, Params } from '@angular/router';
import { Observable, Subscription } from 'rxjs/Rx';
export class ProjectDetailComponent implements OnInit, OnDestroy, AfterViewInit {
private subscription: Subscription;
constructor(
private route: ActivatedRoute,
private router: Router
) { }
ngOnInit(){}
ngAfterViewInit(){
this.subscription = this.router.events.subscribe(val => {
if (val instanceof NavigationEnd) {
(<any>window).twttr = (function (d, s, id) {
let js: any, fjs = d.getElementsByTagName(s)[0],
t = (<any>window).twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = 'https://platform.twitter.com/widgets.js';
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function (f: any) {
t._e.push(f);
};
return t;
}(document, 'script', 'twitter-wjs'));
if ((<any>window).twttr.ready())
(<any>window).twttr.widgets.load();
}
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Basically, I subscribe the widget data until NavigationEnd
then unsubscribe it in ngOnDestroy
, so I can still remain the data between route switch. I believe the logic is correct as the solution worked for someone also, but to me it never worked until this moment.
Try this, no need to subscribe or timeout.
ngOnInit() {
(<any>window).twttr.widgets.load();
}
I know this is an old question, but I got a better solution than setting a timeout. The code I posted as solution in this question is broken since late Angular 4 or early Angular 5 - I don't remember. I will update my answer there too.
So, to fix this, just put the code in the constructor (so the widget loads before the view) like so:
import { Component, OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
@Component({ ... })
export class HomeComponent implements OnDestroy {
private twitter: any;
constructor(private _router: Router) {
this.initTwitterWidget();
}
initTwitterWidget() {
this.twitter = this._router.events.subscribe(val => {
if (val instanceof NavigationEnd) {
(<any>window).twttr = (function (d, s, id) {
let js: any, fjs = d.getElementsByTagName(s)[0],
t = (<any>window).twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function (f: any) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));
if ((<any>window).twttr.ready())
(<any>window).twttr.widgets.load();
}
});
}
ngOnDestroy() {
this.twitter.unsubscribe();
}
}
If I find any information on why previous code was broken, I'll update this answer. (Or if anyone else knows, feel free to edit this)
Okay, I found a way to work around based on this reference (Why will my twitter widget not render if i change the view in angularjs?). No need for event subscription, I need to wrap the function into setTimeOut
to re-render it between route switch. Remember to also wrap the setTimeOut
function inside isPlatformBrowser
for a better practice of pre-rendering. Here is the code:
import { Component, OnInit, OnDestroy, AfterViewInit, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
constructor(@Inject(PLATFORM_ID) private platformId: Object) { }
ngAfterViewInit() {
if (isPlatformBrowser(this.platformId)) {
setTimeout(function() {
(<any>window).twttr = (function(d, s, id) {
let js, fjs = d.getElementsByTagName(s)[0],
t = (<any>window).twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = 'https://platform.twitter.com/widgets.js';
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, 'script', 'twitter-wjs'));
(<any>window).twttr.widgets.load(); }, 100);
}
}
来源:https://stackoverflow.com/questions/47176195/embedded-twitter-widget-on-angular-2-app-only-shows-up-on-the-first-page-load