React-dnd: Verwenden Sie innerhalb und / oder mit einem Iframe.

Erstellt am 20. Juli 2015  ·  22Kommentare  ·  Quelle: react-dnd/react-dnd

Wenn sich Kontext, Quelle und Ziel in einem Iframe befinden, kann DnD nicht verschoben werden. Ich habe es bis zum HTML5.js-Backend zurückverfolgt, das mit DnD geliefert wird.
Obwohl ich denke, dass es etwas mit einem Renderer im Iframe zu tun haben könnte. Hier ist ein Beispiel für Codepen http://codepen.io/mattconde/pen/zGLXML?editors=101

enhancement wontfix

Hilfreichster Kommentar

Nach vielen Versuchen gelang es mir, Elemente in einem Iframe wie diesem abzulegen:

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>

Scheint dies der richtige Weg zu sein?

Alle 22 Kommentare

Das Ziehen / Ablegen über Frames hat auch bei mir nicht funktioniert. Es scheint, als müssten Drag / Drop-Ereignisse nur auf das Fensterobjekt jedes weiteren Frames angewendet werden. Derzeit werden sie nur von dem Fensterobjekt abgerufen, in dem Sie Ihre Reaktions-App ausführen:

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

Ich habe das HTML5-Backend in meinem letzten Projekt mit einem Affen gepatcht, damit es funktioniert ( setup und teardown akzeptieren ein alternatives win Fensterobjekt):

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

Außerdem muss die Backend-Instanz irgendwie verfügbar gemacht werden (mehr Affen-Patches in DragDropContext.js ...), um setup Bedarf teardown auszuführen (beim Einrichten Ihrer Frames). .

Aber wenn das erledigt ist, funktioniert es wie ein Zauber: D.

Oh wow schöner Fund, macht sehr viel Sinn. Kann die Änderung in DragDropContext.js vermieden werden, wenn Sie es später heute versuchen werden? Auf diese Weise könnten wir einfach ein neues Backend erstellen, wie in den Dokumenten erwähnt.

Ich freue mich, einen spezifischen API- und Implementierungsvorschlag zu erwägen, der dies behebt.
Leider ist es schwer zu verstehen, was genau geändert wurde und warum.

Nehmen wir an, wir unterstützen vorerst keine Iframes.

@gaearon Ich versuche, einen Drag & Drop-Seitenersteller zu erstellen. Versuchte alles andere und es ist schrecklich, mit Flussmitteln zu arbeiten. Können Sie mir einige Hinweise geben, wo ich Änderungen vornehmen muss, damit es vom Crossframe aus funktioniert?

@nadimtuhin Ich habe selbst an einem Cross-Frame-Seitenersteller gearbeitet, als ich das Problem angesprochen habe, und ich werde diese Woche wieder damit beginnen, eine Lösung mit mehreren Fenstern zum

Für mich bin ich mir nicht sicher, ob es die beste Lösung wäre, in iframes zu arbeiten, es wäre sicher schön. Das Ziel zu erreichen, dass React-Dnd über mehrere Apps hinweg funktioniert, scheint jedoch die bessere Option zu sein.

Ich habe gestern einen kurzen Blick darauf geworfen und nur einige der Handles im HTML5-Backend protokolliert. und die Quelle aus dem ersten Fenster wird auf dem Ziel aus dem zweiten erkannt. Aber so weit bin ich gekommen.

@gaearon Einige Hinweise / Hinweise, wo man suchen sollte, wären großartig, um meine ersten echten Open-Source-Beiträge zu machen / zu versuchen.

@mattconde nein Ich verwalte iframe nicht in meiner Reaktions-App. Ich habe vor, zwei verschiedene Apps auf zwei verschiedenen Frames zu haben. Das übergeordnete Fenster enthält die Logik für die Datenmanipulation und den untergeordneten Rahmen für die Präsentation. Das Kind bekommt seine Requisiten aus dem Flussmittelgeschäft der Eltern.

@ Mattconde

Es fällt mir schwer, neben "Versuchen Sie, Protokolle in das HTML5-Backend einzufügen und es dann zu optimieren" Hinweise zu geben. Nehmen Sie das einfachste Beispiel und sehen Sie, ob Sie es zum Laufen bringen können. Das Backend macht nur eines: Abonniert Fensterereignisse und Knotenereignisse und übersetzt sie in Aktionen. Ich weiß nicht genug darüber, wie Iframes funktionieren. Möglicherweise müssen Sie den Code ändern, um nicht das Fenster, sondern das oberste Fenster (oder den Iframe) eines bestimmten Knotens zu abonnieren, wenn dies sinnvoll ist. Aber ich bin hier weit aus meiner Tiefe heraus, also rede ich vielleicht Müll.

@mattconde @gaearon

Ich hatte vor kurzem das gleiche Problem. Der Grund dafür ist, dass HTML5Backend Ereignis-Listener für das Fenster festlegt. Wenn Sie es jedoch in iframe verwenden möchten, sollten Sie sie beispielsweise für window.frames [0] festlegen.

@gaearon Was halten Sie von einer Option zum Übergeben des Kontexts an die Setup- / Teardown-Funktion in HTML5Backend.js?

Ich habe das gleiche Problem festgestellt, indem ich einen erweiterten Editor (Text, Bilder usw.) erstellt habe, der innerhalb eines Iframes funktioniert, und ich muss Elemente (Text, Bild) per Drag & Drop in diesen ziehen, im Grunde genommen per Drag & Drop, um die Elemente zu ändern Auftrag.

Ich habe ein Problem unter https://github.com/gaearon/react-dnd/issues/435 geöffnet und nur herausgefunden, dass es am Iframe liegt. Ich werde versuchen, es zu "optimieren", aber wenn es eine Problemumgehung gibt, würde ich mich freuen, es zu wissen! :) :)

Ich versuche, eine PR zu erstellen, damit sie mit Iframes funktioniert. Derzeit läuft es noch nicht, ich habe Probleme herauszufinden, wie ich setup und teardown aufrufen kann, jeweils in meinen componentDidMount und componentWillUnmount Methoden.

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

@Vadorequest Klingt so, als würden wir beide ein ähnliches Endprodukt anstreben. Ich habe es nicht dazu gebracht, mit react-dnd vom Eltern- zum Kinderfenster zu arbeiten. Die Arbeit, für die ich mich entschieden habe, bestand darin, meine Editor-App (übergeordnet) und eine Vorschau-App (untergeordnet) zu haben. Die Vorschau-App wurde erst gerendert, als eine Verbindung zum Redux-Store des Editors hergestellt werden konnte.

Dann hatte ich in meinem Redux-Shop eine Liste von Vorlagen, die der Benutzer aus dem Editor auf eine großartige Inhaltsseite ziehen soll. Meine Vorlagenliste befand sich also im Editorfenster, aber ich möchte sie in die Vorschau ziehen.

Dank react-dnd , das native Typen unterstützt, konnte ich im Editorfenster Textzüge erstellen, um die Informationen zu übergeben, die für jede zu rendernde Vorlage erforderlich sind. Mein Code-Snippet ...

    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;
    },

Dann könnte ich diesen JSON-String am anderen Ende mit react-dnd fangen, der wirklich gut funktioniert.

Lassen Sie mich wissen, wie es Ihnen geht, und würden gerne etwas über alternative Möglichkeiten erfahren.

@mattconde Ich arbeite an zwei separaten Zweigen, einem hässlichen Fix und einem echten Fix dafür. Das hässliche Update ändert einfach diese Zeilen in der Datei HTML5Backend.js . Änderungen können hier eingesehen werden: https://github.com/Gutenberg-Technology/react-dnd-html5-backend/commit/8b3d6a44b2cdbfe8d5bac025fc263715968d8b6c

_ (Es wird im Grunde nur ein target -Parameter zu setup und teardown target hinzugefügt, der meinen Iframe als Standardwert hat und auf die Verwendung von window zurückgreift. Das Update ist so hässlich, dass es tatsächlich fehlschlagen würde, wenn kein Iframe gefunden wird, aber es reicht für den Moment.) _

Aber dies wird wahrscheinlich in einigen Situationen fehlschlagen, wenn es mehr als einen Iframe gibt, also nur, um nicht hängen zu bleiben. Eine bessere Lösung wäre, setup und teardown in meinem eigenen Code manuell aufzurufen, indem Sie einfach einen target -Parameter übergeben, um die Listener zu binden und die Bindung aufzuheben.

Vielen Dank für die Erläuterung Ihrer Lösung. Ich werde meine PR auf jeden Fall verbessern, wenn ich in naher Zukunft eine bessere Problemumgehung finde. :) :)

Hey Leute, bin gerade selbst auf dieses Problem gestoßen und kann nicht herausfinden, wie man ein Fenster mit einem Iframe verbindet. Zum Beispiel möchte ich DragSource im Fenster haben und DropTarget im Iframe erstellen, auch wenn ich HTML5Backend optimiere, kann ich es nicht so zum Laufen bringen ...

@mattconde Danke, dass

@gaearon Die PRs hier ☝️ ermöglichen React-Dnd, um Iframes zu unterstützen. Wenn Sie Bedenken haben oder ich etwas ändern muss, lassen Sie es mich wissen.

@kesne Bist du der neue Betreuer? Können Sie diese PRs überprüfen?

Hallo @darthtrevino
Ermöglichen Ihre Änderungen das Ziehen eines Elements von der Seite in einen Frame?
Ich kann innerhalb und außerhalb des Rahmens ziehen und ablegen.

Hey @crysislinux , ich möchte diese Bibliothek auf Angular 2 portieren und würde gerne sehen, was ihr euch

Gibt es eine Möglichkeit, Elemente, die sich außerhalb des Iframes befinden, innerhalb des Iframes abzulegen, zum Beispiel:

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

Nach vielen Versuchen gelang es mir, Elemente in einem Iframe wie diesem abzulegen:

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>

Scheint dies der richtige Weg zu sein?

Ich habe auch Probleme mit der Verwendung von dnd in einem Iframe (keine übergeordnete Interaktion). Das Ziehen funktioniert einwandfrei, aber Drop-Zonen funktionieren nicht mehr. Was ist die Lösung, um Drop-Zones innerhalb eines Iframes funktionieren zu lassen (indem Sie das Objekt nur vollständig innerhalb des Iframes verschieben)?

Ich möchte darauf hinweisen, dass es mit dem Touch-Backend funktioniert, aber nicht mit dem HTML5-Backend.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen