今時ホームページにツイートボタン載せるだけでハマることなんてあります??????(執筆日2018年4月23日)
だって、 https://publish.twitter.com/ にアクセスして、生成したコードを自分のページに貼り付けるだけじゃないですか!!!!!
……って思ってたんですけどね。
ハマるんですよ、それが。そう、Angularならね。
ちなみにAngularのバージョンは5.2.9です。
普通にやるとどうなるの?
上記のサイトで生成したコードがこちら。
<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-size="large" data-text="シェアしたいテキスト!" data-url="http://example.com" data-hashtags="hogehoge" data-show-count="false">Tweet</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
タグが2つ並んでます。
属性がいろいろついたa
タグと、外部JSを実行するscript
タグです。
仕組みとしては、上から順にページを読み込んでいく時に、
- まず
a
タグが読み込まれて、 - 次に
script
タグが読み込まれてwidgets.js
が実行され、 - 先に読み込まれていた
a
タグがツイートボタンに書き換えられる、
という感じです。
だから、要するに
-
a
タグを読み込み -
widgets.js
を実行する
の2点さえやればいいんですが
Angularのコンポーネントにこのコードをただ記述すると、これがうまくいかないんですね。
なんと2点とも、うまくいきません。
それぞれ説明します。
問題1 script
タグが読み込まれない
コンポーネントにscript
タグが含まれていると、そのまま出力してくれないみたいです。
開発サーバーで動かしてブラウザで確認すると、script
タグがまるまるなくなってました。
これではいけませんね。a
タグを書き換えてボタンにする作業が行われなくなってしまいます。
解決策1
参考にした質疑
https://teratail.com/questions/70842
ngAfterViewInitについて
https://angular.io/guide/lifecycle-hooks#afterview
要素の追加について
https://qiita.com/kouh/items/dfc14d25ccb4e50afe89
これらを参考にしました。
つまり、a
タグは普通に書いておいて、後から動的にscript
タグを追加して、追加した瞬間即実行してもらうことで、a
タグを書き換えるというものです。
このscript
タグの追加は、a
タグを書いた後で行われる必要があるので、
AngularコンポーネントのライフサイクルフックのうちAfterViewInit
で実行させましょう。
これでOKですね…………?????
はい。これだけでは、だめなんですね。
問題2 a
タグの中身が書き換わる
同じ状況の人(上と同じ人)
https://teratail.com/questions/71021
こちらの質問と同じ状況です。(回答が付いてなかったので、解決策は自力で考えました。)
Angularのコンポーネントに記述したタグは、そのタグに付与している属性によっては書き換えが行われるんですね。*ngFor
とかありますからね。そりゃそうなんですけど
どうも、このツイートボタンのa
タグに付与する属性の名前とバッティングしてるのか
a
タグが書き換わっちゃうんですよね。
<a data-text="hoge"></a>
が<a>hoge</a>
に変わっちゃう、みたいなことが起こります。
この状態では、後からscript
タグを追加してwidget.js
を実行しても、元が書き換わってるので、ツイートボタンへの変身がうまくいきません。
解決策2
ということで
だったら、そのa
タグ自体も、あとから動的に追加してやればいいですね。
言われてみればなるほどという感じ。
最終的な解決策
最終的な解決策は
「ツイートボタン関連のコードを、全部あとから動的に追加する」ということになります。
テンプレートのhtml
ファイルに直接書くのではなく、ということです。
使うのはコンポーネントのライフサイクルフックのうちngAfterViewInit
です。
ということで、コードはこんな感じ。
ngAfterViewInit(){
var element = document.createElement('a');//aタグを作ります
element.setAttribute('href',"https://twitter.com/share?ref_src=twsrc%5Etfw");
element.setAttribute('class',"twitter-share-button");
element.setAttribute('data-size',"large");
element.setAttribute('data-text',"シェアしたいテキスト!");
element.setAttribute('data-url',"http://example.com");
element.setAttribute('data-hashtags',"hogehoge");
element.setAttribute('data-show-count',"false");
var script = document.createElement('script');//scriptタグを作ります
script.async = true;
script.setAttribute('src',"https://platform.twitter.com/widgets.js");
script.setAttribute('charset','utf-8');
//aタグ、scriptタグの順で設置します
var div = document.getElementById("foobaa");//ボタンを置きたい場所の手前の要素を取得
div.parentNode.insertBefore(element,div.nextSibling);//ボタンを置きたい場所にaタグを追加
div.parentNode.insertBefore(script,div.nextSibling);//scriptタグを追加してJSを実行し、aタグをボタンに変身させる
}
本来ただコードを貼り付けるだけでいいのに、随分面倒になりましたね。もしもっと簡単になる方法があれば教えて下さい。directiveとかをうまく使えるのかなあ?
あとあんまり関係ないですが、最後にボタンを置きたい場所周辺の要素を取得する時に、`document.getElementsByClass'を使ったら、返ってくるのはDOM要素のコレクション(配列みたいなもの)なんですね。ここもちょっとハマったので気をつけて下さい。