web-dev-qa-db-ja.com

新しいタブで新しいウィンドウを開く

ユーザーが次のボタンをクリックすると、新しいウィンドウを開こうとしています:

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

動作させるために修正する方法は?

31
Rhushikesh

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