React-dnd: 内部および/またはiframeと一緒に使用します。

作成日 2015年07月20日  ·  22コメント  ·  ソース: react-dnd/react-dnd

コンテキスト、ソース、およびターゲットがiframe内にある場合、DnDはシフト解除に失敗します。 DnDに付属しているHTML5.jsバックエンドまで追跡しました。
iframeでの再レンダリングと関係があると思いますが。 これがcodepenの例ですhttp://codepen.io/mattconde/pen/zGLXML?editors=101

enhancement wontfix

最も参考になるコメント

何度も試した後、次のようにiframe内に要素をドロップすることができました。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import FrameComponent from 'react-frame-component';

class DragDropAwareIFrame extends Component {
  static propTypes = {
    innerRef: PropTypes.func,
  };

  static contextTypes = {
    dragDropManager: PropTypes.object.isRequired,
  }

  constructor(props, context) {
    super(props, context);

    this.manager = this.context.dragDropManager;
  }

  componentDidMount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().addEventListeners(iframe.contentWindow);
  }

  componentWillUnmount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().removeEventListeners(iframe.contentWindow);
  }

  handleRef = (el) => {
    this.iframe = el;
    if (this.props.innerRef) this.props.innerRef(el);
  }

  render() {
    const { innerRef, ...props } = this.props;
    return <FrameComponent {...props} ref={this.handleRef} />;
  }
}

<DragDropContextProvider backend={HTML5Backend}>
    <div>
        <Item />
        <DragDropAwareIFrame>
            <div>
                <Dustbin />
            </div>
        </DragDropAwareIFrame>
    </div>
</DragDropContextProvider>

これは正しい方法のように思われますか?

全てのコメント22件

箱から出して、フレーム間でのドラッグアンドドロップも機能しませんでした。 ドラッグアンドドロップイベントは、追加の各フレームのウィンドウオブジェクトに適用する必要があるようです。 現在、reactアプリを実行しているウィンドウオブジェクトのみがそれらを取得します。

https://github.com/gaearon/react-dnd/blob/master/src/backends/HTML5.js#L130 -L139

最近のプロジェクトでHTML5バックエンドにモンキーパッチを適用して機能させました( setupteardownは代替のwinウィンドウオブジェクトを受け入れます):

https://gist.github.com/rasmusfl0e/39db428399bd196ef706

また、必要に応じて(フレームの設定で) setupteardownを実行するために、バックエンドインスタンスを何らかの方法で公開する必要があります( DragDropContext.jsでモンキーパッチを追加...)。 。

しかし、それが完了すると、それは魅力のように機能します:D

ああすごい素敵な発見、多くの意味があります。 今日の後半に試してみる予定ですが、DragDropContext.jsの変更を回避できますか? そうすれば、ドキュメントに記載されているような新しいバックエンドを作成できます。

これに対処する特定のAPIと実装の提案を検討できてうれしいです。
残念ながら、正確に何が変更されたのか、そしてその理由を要点から理解するのは困難です。

今のところ、iframeをサポートしていないとしましょう。

@gaearonドラッグアンドドロップページビルダーを構築しようとしています。 他のすべてを試してみましたが、フラックスを扱うのは恐ろしいことです。 クロスフレームから機能するように調整する場所の手がかりを教えてください。

@nadimtuhinこの問題を提起したとき、私は自分でクロスフレームページビルダーに取り組んでいました。今週は、マルチウィンドウソリューションの動作を再開します。 あなたはreactでiframeを管理していますか?

私にとって、iframe内での作業がこれ以上最善の解決策になるかどうかはわかりませんが、それは確かに素晴らしいことです。 しかし、react-dndを複数のアプリで機能させることを目的とすることは、より良い選択肢のように思われます。

昨日簡単に調べて、html5バックエンドのハンドルの一部をログに記録しました。 そして、最初のウィンドウからのソースが2番目からのターゲットで検出されています。 しかし、それは私が得た限りです。

@gaearonどこを見ればよいか

@mattcondeいいえ私はreactアプリ内でiframeを管理していません。 2つの異なるフレームに2つの異なるアプリを配置する予定です。 親ウィンドウには、データ操作用のロジックと表示用の子フレームがあります。 子供は親フラックスストアから小道具を入手します。

@mattconde

「ログをHTML5バックエンドに入れてから、微調整を開始する」以外の指針を示すのは難しいです。 可能な限り単純な例を取り上げて、それを機能させることができるかどうかを確認してください。 バックエンドは1つのことだけを行います。ウィンドウイベントとノードイベントをサブスクライブし、それらをアクションに変換します。 iframeがどのように機能するかについてはよくわかりません。 おそらく、ウィンドウではなく、特定のノードのトップレベルウィンドウ(またはiframe)にサブスクライブするようにコードを変更する必要があります(これが理にかなっている場合)。 しかし、私はここで私の深さから遠く離れているので、私はゴミを話しているかもしれません。

@mattconde @gaearon

最近同じ問題が発生しました。 失敗する理由は、HTML5Backendがイベントリスナーをウィンドウに設定するためですが、iframe内で使用する場合は、たとえばwindow.frames [0]に設定する必要があります。

@gaearon HTML5Backend.jsのセットアップ/ティアダウン関数にコンテキストを渡すオプションについてどう思いますか?

私は同じ問題に直面しています。iframe内で機能する拡張エディター(テキスト、画像、..)を構築し、その中に要素(テキスト、img)をドラッグアンドドロップする必要があります。基本的に、要素をドラッグアンドドロップして変更します。注文。

問題https://github.com/gaearon/react-dnd/issues/435を開いたところ、iframeが原因であることがわかりました。 「微調整」しようと思いますが、回避策があれば教えていただければ幸いです。 :)

iframeで動作するようにPRを作成しようとしています。 現在進行中ですが、まだ機能していません。それぞれcomponentDidMountcomponentWillUnmount setupteardownを呼び出す方法を理解するのに問題があります。 componentWillUnmountメソッド。

https://github.com/gaearon/react-dnd-html5-backend/pull/27

@Vadorequest私たち二人が同じような最終製品を目指しているようですね。 親から子のウィンドウまでreact-dnd動作するようにはなりませんでした。 私が決めた回避策は、エディター(親)アプリとプレビュー(子)アプリを用意することでした。 プレビューアプリは、エディターのreduxストアに接続できるようになるまでレンダリングされませんでした。

次に、reduxストアに、ユーザーがエディターから優れたコンテンツページにドラッグするテンプレートのリストがありました。 そのため、テンプレートリストはエディタウィンドウに表示されていましたが、プレビューにドラッグしたいと思います。

ネイティブタイプをサポートするreact-dndおかげで、エディターウィンドウにテキストドラッグを設定して、レンダリングする各テンプレートに必要な情報を渡すことができました。 私のコードスニペット...

    componentDidMount() {
        this.refs.template.addEventListener('dragstart', this.handleDragStart, false);
    },
    componentWillUnmount() {
        this.refs.template.removeEventListener('dragstart', this.handleDragStart, false);
    },
    handleDragStart(e) {
        const { template } = this.props;
        e.dataTransfer.setData('text/plain', JSON.stringify({
            type: template.type,
            name: template.name,
        }));
        return e;
    },

次に、もう一方の端がreact-dndであるJSON文字列をキャッチでき、非常にうまく機能します。

あなたがどのように乗り込むかを教えてください、それを回避する別の方法について聞いてみたいです。

@mattconde私は2つの別々のブランチ、醜い修正とこれに対する実際の修正に取り組んでいます。 醜い修正は、 HTML5Backend.jsファイルのそれらの行を変更するだけです。 変更はここで表示できます: https

_(基本的にはtargetパラメータをsetupteardownに追加するだけで、iframeがデフォルト値として使用され、 window使用にフォールバックします。修正非常に醜いので、iframeが見つからないと実際には失敗しますが、今のところは失敗します。)_

ただし、複数のiframeがある場合、これは状況によっては失敗する可能性が高いため、スタックしないようにするだけです。 より良い解決策は、リスナーをバインドおよびバインド解除するためにtargetパラメーターを渡すだけで、自分のコード内でsetupおよびteardownを手動で呼び出すことです。

あなたの解決策を説明してくれてありがとう、近い将来より良い回避策を見つけたら、私は間違いなく私のPRを改善します。 :)

やあみんな、自分でこの問題に遭遇しただけで、ウィンドウをiframeに接続する方法がわかりません。 たとえば、ウィンドウにDragSourceを配置し、iframeにDropTargetを作成したいのですが、HTML5Backendを微調整しても、そのように機能させることはできません...

@mattcondeこれを共有していただきありがとうございます。 私は私が思う同様の最終製品を構築しています。 さらに悪いことに、Angular 2を使用しています。react-dndを部分的にAngularに移植しましたが、最後にiframeで壁にぶつかりました。 あなたの方法を試してみるつもりです。

@gaearonここのPR☝️はreact-dndがiframeをサポートすることを可能にします。 懸念がある場合、または何かを変更する必要がある場合は、お知らせください。

@kesneあなたは新しいメンテナですか? これらのPRを確認できますか?

こんにちは@darthtrevino
変更により、要素をページからフレームにドラッグできますか?
フレームの内側と外側にドラッグアンドドロップできます。

ねえ@crysislinux 、私はこのライブラリをAngular 2に移植したいと思っており、皆さんが思いついたものを見てみたいと思います。 コードを共有してもよろしいですか? ありがとう!

たとえば、iframeの外側にあるアイテムをiframeの内側にドロップする方法はありますか?

<DragDropContextProvider backend={HTML5Backend}>
    <div>
        <Item />
        <Frame>
            <div>
                <Dustbin />
            </div>
        </Frame>
    </div>
</DragDropContextProvider>

何度も試した後、次のようにiframe内に要素をドロップすることができました。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import FrameComponent from 'react-frame-component';

class DragDropAwareIFrame extends Component {
  static propTypes = {
    innerRef: PropTypes.func,
  };

  static contextTypes = {
    dragDropManager: PropTypes.object.isRequired,
  }

  constructor(props, context) {
    super(props, context);

    this.manager = this.context.dragDropManager;
  }

  componentDidMount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().addEventListeners(iframe.contentWindow);
  }

  componentWillUnmount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().removeEventListeners(iframe.contentWindow);
  }

  handleRef = (el) => {
    this.iframe = el;
    if (this.props.innerRef) this.props.innerRef(el);
  }

  render() {
    const { innerRef, ...props } = this.props;
    return <FrameComponent {...props} ref={this.handleRef} />;
  }
}

<DragDropContextProvider backend={HTML5Backend}>
    <div>
        <Item />
        <DragDropAwareIFrame>
            <div>
                <Dustbin />
            </div>
        </DragDropAwareIFrame>
    </div>
</DragDropContextProvider>

これは正しい方法のように思われますか?

@ethanve重複の問題からこのスレッドをhttps://cormacrelf.github.io/angular-skyhook/

また、iframe内でdndを使用するのに問題があります(親の相互作用なし)。 ドラッグは正常に機能しますが、ドロップゾーンは機能しなくなります。 ドロップゾーンをiframe内で機能させるためのソリューションは何ですか(アイテムを完全にiframe内に移動するだけです)。

タッチバックエンドでは機能しますが、HTML5バックエンドでは機能しないことを指摘しておきます。

このページは役に立ちましたか?
0 / 5 - 0 評価