Search code examples
javascriptangularangular2-routingtwitter-widget

Twitter widget on Angular 2


I created a Twitter widget and I'm trying to put it in my Angular 2 project, but the JS file does not work.

If I insert it with JS (Here) it works, but when I switch to another tab and back (I have Angular Routing installed) it disappears and shows whatever is in A tag (so, "Tweets by ...").

HTML code (it's in home component):

<md-card-content>
  <a class="twitter-timeline" data-lang="en" data-height="350" data-theme="light" data-chrome="noborders nofooter noheader noscrollbar transparent" href="https://twitter.com/profile">Tweets by profile</a>
</md-card-content>

Script in home.component.ts, the code was provided by @Arg0n (look in answers section):

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

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

  constructor(private _router : Router) { }

  public ngOnInit() {
    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"));
        twttr.widgets.load();
      }
    })
  }

}

EDIT: Alright, I did some research and found out that I have to load the widget again with twttr.widgets.load(); but doing that, it throws me an error.

I edited the code above, so you can see what I've tried. The code above returns an error:

[ts] Cannot find name 'twttr'

if I append (window). to it, it throws me this:

EXCEPTION: Uncaught (in promise): TypeError: Cannot read property 'load' of undefined

The documentation on load property is here: https://dev.twitter.com/web/javascript/initialization


Solution

  • Alright, I found a solution to this. When we switch between Angular routers, the widget unloads. That's why we put a subscriber, so we load the widget every time we switch between tabs. We can see here how to load the widget for lazy-loading content. When the page is ready, we can use that function to load the widget. Don't forget to unsubscribe after the view is destroyed!

    Code:

    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();
      }
    }