2017-11-09 18 views
3

私はTypeScriptとReactで作業しています。ダイアログウィンドウである私のコンポーネントでは、ボタンなどのトリガ要素をプロパティとして保存したいと考えています。コンポーネントがアンマウントすると、その要素にフォーカスを戻したいと思います。しかし、TSLintから、解決方法がわからないというエラーが表示されています。TypeScript - 'Element'はHTMLInputElementに割り当てられません

class Dialog extends React.Component<Props, {}> { 
    ... 
    focusedElementBeforeDialogOpened: HTMLInputElement; 

    componentDidMount() { 
    this.focusedElementBeforeDialogOpened = document.activeElement; 
    ... 
    } 
    ... 
} 

私はプロパティの値を代入してい行にエラーを受信して​​います。私はElementあるいはHTMLInputElementにプロパティの種類を変更した場合しかし、私はエラーが表示さ

[ts] Type 'Element' is not assignable to type 'HTMLInputElement'. 
    Property 'accept' is missing in type 'Element'. 

componentWillUnmount()

componentWillUnmount() { 
    ... 
    this.focusedElementBeforeDialogOpened.focus(); 
} 

このエラーは、focus()方法を持たない要素タイプに関してです。

質問

document.activeElementは、入力タイプであることを活字体を伝える方法はありますか?

this.focusedElementBeforeDialogOpened = <HTMLInputElement>document.activeElement;

またはこの周りのより良い方法があるようなものはそうdocument.activeElement.focus()の両方をサポートする型を宣言しますか? document.activeElementのドキュメントから

+0

私が反応に慣れていないんだけど角度で、あなたは 'nativeElementを持っているが'プロパティ。あなたは 'activeElement'の後にそれを持っていませんか? – trichetriche

答えて

1

それが一度にテキストの選択を持っている場合は多くの場合、これは、<input>または<textarea>オブジェクトを返します。その場合は、要素のselectionStartプロパティとselectionEndプロパティを使用して詳細を取得できます。フォーカスされた要素は、<select>要素(メニュー)または<input>要素で、ボタン、チェックボックス、またはラジオのタイプである場合もあります。ある

は、document.activeElementは必ずしもHTMLInputElementのインスタンス(それはまた、等をHTMLSelectElementことができる)ではありません。

あなたは確かにだけHTMLInputElementを探しているなら、あなたは活字体によって認識される単純なinstanceof型ガードを使用することができますが:

componentDidMount() { 
    if (document.activeElement instanceof HTMLInputElement) { 
     this.focusedElementBeforeDialogOpened = document.activeElement; 
    } 
    ... 
} 

要素がある場合はさらに、あなたは検出することができフォーカス可能な、例えば独自の型ガードを定義することにより:その後、

interface IFocusableElement { 
    focus(): void; 
} 

function isFocusable(element: any): element is IFocusableElement { 
    return (typeof element.focus === "function"); 
} 

そしてthis.focusedElementBeforeDialogOpenedの種類と独自の型ガードとしてIFocusableElementを使用します。あなたもElementによって提供されるオリジナルのAPIが必要な場合は

focusedElementBeforeDialogOpened: IFocusableElement; 

componentDidMount() { 
    if (document.activeElement && isFocusable(document.activeElement)) { 
     this.focusedElementBeforeDialogOpened = document.activeElement; 
    } 
    ... 
} 

、することができますちょうど交差点のタイプを使用します。

focusedElementBeforeDialogOpened: IFocusableElement & Element; 
+0

HTMLInputElementはを返すだけなので、可能な型にHTMLButtonElementを追加し、

+0

このソリューションにはいくつかのエレガントな部分がありますが、 'document.activeElement'に' focus'メソッドがない場合、 'componentWillUnmount()'は 'undefined'で' this.focusedElementBeforeDialogOpened.focus(); –

0

は確かに、lib.es6.d.tsの定義は双方向ですそれは少し混乱しているW3C仕様でない限りトン矛盾は、:だから

interface Document extends [...] { 
    /** 
    * Gets the object that has the focus when the parent document has focus. 
    */ 
    readonly activeElement: Element; 
    [...] 
    focus(): void; 
    [...] 
} 

interface HTMLElement extends Element { 
    [...] 
    focus(): void; 
    [...] 
} 

、唯一の種類我々は、手動でピントを合わせることができ、オブジェクトの2はDocumentHtmlElementですが、どのElementが集中することができます!

あなただけのバックフォーカスを与える必要がある場合は、あなたのような何かを行うことができます。

class Dialog extends React.Component<Props, {}> { 
    private resetFocus =() => {}; 

    componentDidMount() { 
     const elementToFocus = document.activeElement instanceof HTMLElement 
      ? document.activeElement 
      : document; 
     this.resetFocus =() => elementToFocus.focus(); 
    } 

    componentWillUnmount() { 
     this.resetFocus(); 
    } 
} 

または

componentDidMount() { 
    const activeElement = document.activeElement as any; 
    if (typeof activeElement.focus === 'function') { 
     this.resetFocus =() => activeElement.focus(); 
    } 
} 
+0

ありがとうございました。フォーカスを返すことは私の懸念ではありません。私はどのようにタイプ 'any'を使用しないようにするかを探そうとしています。 – Yuschick

+0

私は不要な 'any'を削除するコードを編集しました。あなたのニーズによく合うかもしれません^^ –

関連する問題