Встроенный виджет Twitter в приложении Angular 2+ отображается только при загрузке первой страницы
Мое приложение работает отлично, если я копирую именно встроенную функцию из документов Twitter ( https://dev.twitter.com/web/javascript/loading) в функцию ngAfterViewInit, но когда я переключаю маршрут, виджет также исчезает.
Вот код для работы только для первой загрузки страницы:
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'));
}
}
Затем я нашел приемлемое решение от этого ( виджет Twitter на Angular 2), но виджет даже не отображается с первой загрузки и никаких ошибок, поэтому я даже не знаю, где я был не прав.
Вот код, который никогда не показывает виджет Twitter без каких-либо ошибок:
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();
}
}
В основном, я подписываю данные виджета до NavigationEnd
затем отписаться в ngOnDestroy
, так что я все еще могу сохранить данные между переключателем маршрута. Я считаю, что логика верна, поскольку решение сработало и для кого-то, но для меня оно никогда не работало до этого момента.
3 ответа
Попробуйте это, не нужно подписываться или тайм-аут.
ngOnInit() {
(<any>window).twttr.widgets.load();
}
Я знаю, что это старый вопрос, но у меня есть лучшее решение, чем установка таймаута. Код, который я разместил в качестве решения в этом вопросе, не работает с поздней версии Angular 4 или ранней версии Angular 5 - я не помню. Я тоже обновлю свой ответ там.
Итак, чтобы это исправить, просто поместите код в конструктор (чтобы виджет загружался перед представлением) примерно так:
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();
}
}
Если я найду информацию о том, почему предыдущий код был нарушен, я обновлю этот ответ. (Или, если кто-то еще знает, не стесняйтесь редактировать это)
Хорошо, я нашел способ обойти это на основе этой ссылки ( Почему мой твиттер-виджет не будет отображаться, если я изменю представление в angularjs?). Нет необходимости подписки на события, мне нужно обернуть функцию в setTimeOut
перерисовать его между переключателем маршрута. Не забудьте также обернуть setTimeOut
функция внутри isPlatformBrowser
для лучшей практики предварительного рендеринга. Вот код:
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);
}
}