Angular4入門_Vol.5
参考サイト
https://www.codingforentrepreneurs.com/projects/try-angular-v4/
Safely Embed a Video
- youtubeのembed(埋め込み)linkを挿入してみる。
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'video-list', templateUrl: './video-list.component.html', styleUrls: ['./video-list.component.css'] }) export class VideoListComponent implements OnInit { title = "Video List!"; // videoList = ["Item 1", "Item 2", "Item 3"]; videoList = [ { name: "Item 1", slug: "item-1", embed: `<iframe width="560" height="315" src="https://www.youtube.com/embed/kzjMI00A1f8" frameborder="0" allowfullscreen></iframe>` }, { name: "Item 2", slug: "item-2", embed: `<iframe width="560" height="315" src="https://www.youtube.com/embed/kzjMI00A1f8" frameborder="0" allowfullscreen></iframe>` }, { name: "Item 3", slug: "item-3", embed: `<iframe width="560" height="315" src="https://www.youtube.com/embed/kzjMI00A1f8" frameborder="0" allowfullscreen></iframe>` }, ] constructor() { } ngOnInit() { } }
- video-list.component.html を修正する。
<p> {{ title }} </p> <p *ngFor='let item of videoList'> <a href="videos/{{ item.slug }}" >{{ item.name }}</a> {{ item.embed }} </p>
- embed linkなはずだが、うまく埋め込まれていない。さらに修正してみる。
<p> {{ title }} </p> <div *ngFor='let item of videoList'> <a href="videos/{{ item.slug }}" >{{ item.name }}</a> <div [innerHTML]='item.embed'></div> <div [innerHTML]='"<h1>Hi there</h1>"'></div> </div>
- これでもembedは機能しない。ので、いろいろと実験してみる。video-listにsomeItemという変数を設定してみる。
export class VideoListComponent implements OnInit { title = "Video List!"; someItem = "<h1>HiHi</h1>"; ... }
<p> {{ title }} </p> <div *ngFor='let item of videoList'> <a href="videos/{{ item.slug }}" >{{ item.name }}</a> <div [innerHTML]='item.embed'></div> <div [innerHTML]='someItem'></div> </div>
- HiHiの方は、htmlが読み込まれた状態で表示される。ただ、埋め込みリンクはうまくいかない。だから、別の方法で、埋め込みリンクを利用してみる。
<p> {{ title }} </p> <div *ngFor='let item of videoList'> <a href="videos/{{ item.slug }}" >{{ item.name }}</a> <div [innerHTML]='item.embed'></div> <div [innerHTML]='someItem'></div> <iframe width="560" height="315" src="https://www.youtube.com/embed/{{ item.embed }}" frameborder="0" allowfullscreen></iframe> </div>
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'video-list', templateUrl: './video-list.component.html', styleUrls: ['./video-list.component.css'] }) export class VideoListComponent implements OnInit { title = "Video List!"; someItem = "<h1>HiHi</h1>"; // videoList = ["Item 1", "Item 2", "Item 3"]; videoList = [ { name: "Item 1", slug: "item-1", embed: `kzjMI00A1f8` }, { name: "Item 2", slug: "item-2", embed: `kzjMI00A1f8` }, { name: "Item 3", slug: "item-3", embed: "" }, ] constructor() { } ngOnInit() { } }
- これでもうまくいかない、、、なぜだ。errorは、
: unsafe value used in a resource URL context (see http://g.co/ng/security#xss)
と表示されているので、たぶんこれが問題だろう。srcの部分をng仕様に変更する。また、embed urlも少し加工したurlを渡すため、getEmbedUrlを定義する。
<p> {{ title }} </p> <div *ngFor='let item of videoList'> <a href="videos/{{ item.slug }}" >{{ item.name }}</a> <div [innerHTML]='item.embed'></div> <div [innerHTML]='someItem'></div> <iframe width="560" height="315" [src]="getEmbedUrl()" frameborder="0" allowfullscreen></iframe> </div>
- video-list.component.tsに追記する。
getEmbedUrl(){ return "https://www.youtube.com/embed/{{ item.embed }}"; }
- これでもだめ!angularのDomSanitizerメソッドをimportして利用してみる。
import { DomSanitizer } from '@angular/platform-browser'; ... constructor(private sanitizer: DomSanitizer) { } // constructorで、sanitizerのアノテーションをDomSanitizerに設定する。 ... getEmbedUrl(){ return this.sanitizer.bypassSecurityTrustResourceUrl('https://www.youtube.com/embed/{{ item.embed }}'); }
- これでどうだ。。。表示された!が、うまく動画が再生されない。{{ item.embed }} の部分の挙動がおかしいので、修正する。
getEmbedUrl(item){ return this.sanitizer.bypassSecurityTrustResourceUrl('https://www.youtube.com/embed/' + item.embed); }
- video-list.component.htmlの方も修正する。
<p> {{ title }} </p> <div *ngFor='let item of videoList'> <a href="videos/{{ item.slug }}" >{{ item.name }}</a> <div [innerHTML]='item.embed'></div> <div [innerHTML]='someItem'></div> <iframe width="560" height="315" [src]="getEmbedUrl(item)" frameborder="0" allowfullscreen></iframe> </div>
- これで無事表示された!!さらに、item.embedに値が入っている場合のみembedを表示するようにする。
<iframe *ngIf='item.embed' width="560" height="315" [src]="getEmbedUrl(item)" frameborder="0" allowfullscreen></iframe>
まとめ
- jsonオブジェクトからのリンクの安全を確保するには、[src]を使うと有効かも?
*ngIf
,[src]
などの文脈で、contextを利用する場合は、''
シングルクオテーションで囲むだけでOK。- それ以外のhtml内で利用する場合は、
{{}}
で囲んで利用する。