ユーザーが次のボタンをクリックすると、新しいウィンドウを開こうとしています:
protected assignActity(type: string): void {
var window = window.open('/#/link');
this.Service.assignActivity(type).subscribe(res => {
window.location = '/#/link/' + res;
console.log(res);
})
}
しかし、それはエラーを投げています:
core.umd.js:3468 TypeError: Cannot read property 'open' of undefined
動作させるために修正する方法は?
window
変数がundefined
である理由は、ローカルスコープでwindowという名前の変数を再度宣言したという事実です。
javascript/TypeScript
のスコープ規則に従って、グローバル変数にアクセスする前に、ローカル変数の値が検索されます。また、変数を最初に宣言するとき、変数は未定義に設定されるため、エラーメッセージが表示されます。
必要なのは、開いているタブの参照をキャプチャする変数名を変更するだけです
var newWindow = window.open('some_url');
ただし、angular2アプリはモバイルなどのさまざまな環境で実行したり、window
オブジェクトが使用可能かどうかに関係なくサーバー側でレンダリングしたりできるため、これは推奨されるアプローチではありません。言うまでもなく、テストでウィンドウオブジェクトをモックするのは非常に難しいでしょう。
代わりに、サービスでwindow
オブジェクトをラップし、そのサービスをコンポーネントに注入できます。この方法では、環境に応じてservice実装をDependency Injection
サービスファイル
@Injectable()
export class WindowRef {
constructor() {}
getNativeWindow() {
return window;
}
}
コンポーネントファイル
@Component({
selector : 'demo',
template : '<div> Demo </div>'
})
class DemoComponent {
nativeWindow: any
constructor( private winRef: WindowRef ) {
this.nativeWindow = winRef.getNativeWindow();
}
protected assignActity(type: string): void {
var newWindow = this.nativeWindow.open('/#/link');
this.Service.assignActivity(type).subscribe(res => {
newWindow.location = '/#/link/' + res;
console.log(res);
})
}