React-dnd: À utiliser à l'intérieur et / ou avec une iframe.

Créé le 20 juil. 2015  ·  22Commentaires  ·  Source: react-dnd/react-dnd

Lorsque le contexte, la source et la cible se trouvent dans une iframe, DnD ne parvient pas à se décaler. Je l'ai suivi dans le backend HTML5.js fourni avec DnD.
Bien que je pense que cela pourrait être quelque chose à voir avec un rendu dans l'iframe. Voici un exemple sur codepen http://codepen.io/mattconde/pen/zGLXML?editors=101

enhancement wontfix

Commentaire le plus utile

Après de nombreux essais, j'ai réussi à déposer des éléments à l'intérieur d'une iframe comme celle-ci:

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>

Cela semble-t-il être la bonne façon de procéder?

Tous les 22 commentaires

Le glisser / déposer hors de la boîte à travers les cadres ne fonctionnait pas non plus pour moi. Il semble que les événements de glisser / déposer doivent simplement être appliqués à l'objet de fenêtre de chaque cadre supplémentaire. Actuellement, seul l'objet de fenêtre dans lequel vous exécutez votre application react les obtient:

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

J'ai mis à jour le backend HTML5 dans mon récent projet pour le faire fonctionner ( setup et teardown acceptant un autre objet de fenêtre win ):

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

Cela nécessite également que l'instance backend soit exposée d'une manière ou d'une autre (plus de patchs de singe dans DragDropContext.js ...) pour exécuter setup et teardown si nécessaire (lors de la configuration de vos cadres) .

Mais une fois que cela est fait, cela fonctionne comme un charme: D

Oh wow belle trouvaille, ça a beaucoup de sens. Vous allez essayer plus tard dans la journée, le changement de DragDropContext.js peut-il être évité? De cette façon, nous pourrions simplement créer un nouveau backend comme le mentionne la documentation.

Je suis heureux d'envisager une API spécifique et une proposition de mise en œuvre pour résoudre ce problème.
Malheureusement, il est difficile de comprendre à partir de l'essentiel ce qui a exactement changé et pourquoi.

Pour l'instant, disons que nous ne prenons pas en charge les iframes.

@gaearon J'essaie de créer un constructeur de page glisser-déposer. J'ai tout essayé et ils sont horribles de travailler avec le flux. Pouvez-vous me donner des indices sur où modifier pour le faire fonctionner à partir d'un cadre croisé?

@nadimtuhin Je travaillais moi-même sur un constructeur de pages à cadres croisés lorsque j'ai soulevé le problème, et je recommencerai à faire fonctionner une solution à fenêtres multiples cette semaine. Gérez-vous l'iframe avec React?

Pour moi, je ne suis pas sûr que travailler dans des iframes soit plus la meilleure solution, ce serait certainement bien. Mais avoir pour objectif de faire fonctionner react-dnd sur plusieurs applications semble être la meilleure option.

J'y ai jeté un bref coup d'œil hier et je viens de connecter quelques-unes des poignées dans le backend html5. et la source de la première fenêtre est détectée sur la cible à partir de la seconde. Mais c'est tout ce que j'ai.

@gaearon Quelques pointeurs / indices comme où chercher serait génial, cherchant à faire / essayer mes premières vraies contributions open source.

@mattconde non Je ne gère pas l'iframe dans mon application

@mattconde

Il m'est difficile de donner des pointeurs à côté de "essayez de mettre des journaux dans le backend HTML5 et ensuite commencez à le peaufiner". Prenez l'exemple le plus simple possible et voyez si vous pouvez le faire fonctionner. Le backend ne fait qu'une chose: s'abonne aux événements de fenêtre et aux événements de nœud, et les traduit en actions. Je ne sais pas assez comment fonctionnent les iframes. Peut-être que vous devez changer le code pour vous abonner non pas à la fenêtre, mais à la fenêtre de niveau supérieur (ou iframe) d'un nœud spécifique si cela a du sens. Mais je suis loin de ma profondeur ici, alors je parle peut-être de bêtises.

@mattconde @gaearon

J'ai eu le même problème récemment. La raison pour laquelle il échoue est que HTML5Backend définit les écouteurs d'événements sur window, mais si vous souhaitez l'utiliser dans iframe, vous devriez plutôt les définir sur, par exemple, window.frames [0].

@gaearon Que pensez-vous d'une option pour passer le contexte à la fonction setup / teardown dans HTML5Backend.js?

J'ai rencontré le même problème, en créant un éditeur amélioré (texte, images, ..) qui fonctionne dans un iframe et j'ai besoin de faire glisser et déposer des éléments (texte, img) à l'intérieur, en gros, faites glisser et déposez les éléments pour changer le ordre.

J'ai ouvert un problème https://github.com/gaearon/react-dnd/issues/435 et je viens de comprendre que c'était à cause de l'iframe. Je vais essayer de "peaufiner" mais s'il y a une solution de contournement, je serais heureux de savoir! :)

J'essaie de faire un PR pour le faire fonctionner avec des iframes. Actuellement en cours, cela ne fonctionne pas encore, j'ai du mal à trouver comment invoquer setup et teardown , respectivement dans mes componentDidMount et componentWillUnmount méthodes.

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

@Vadorequest On dirait que nous react-dnd de la fenêtre parent à enfant. Le travail autour duquel je me suis installé était d'avoir mon application éditeur (parent) et une application de prévisualisation (enfant). L'application de prévisualisation n'a pas été rendue tant qu'elle n'a pas pu se connecter au magasin redux des éditeurs.

Ensuite, dans mon magasin redux, j'avais une liste de modèles que je souhaite que l'utilisateur fasse glisser de l'éditeur vers une page de contenu. Ma liste de modèles se trouvait donc dans la fenêtre de l'éditeur, mais je voudrais les faire glisser vers l'aperçu.

Grâce à la prise en charge des types natifs par react-dnd , j'ai pu configurer des glissements de texte dans la fenêtre de l'éditeur pour transmettre les informations nécessaires à chaque modèle à rendre. Mon extrait de code ...

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

Ensuite, je pourrais attraper cette chaîne JSON à l'autre extrémité avec react-dnd , fonctionne très bien.

Faites-moi savoir comment vous vous en sortez, je serais ravi d'entendre d'autres moyens de contourner cela.

@mattconde Je travaille sur deux branches distinctes, un correctif laid et un vrai correctif pour cela. Le vilain correctif modifie simplement ces lignes dans le fichier HTML5Backend.js . Les modifications peuvent être consultées ici: https://github.com/Gutenberg-Technology/react-dnd-html5-backend/commit/8b3d6a44b2cdbfe8d5bac025fc263715968d8b6c

_ (il suffit d'ajouter simplement un paramètre target à setup et teardown , qui a mon iframe comme valeur par défaut et revient à utiliser window . Le correctif est si moche que cela échouerait si aucune iframe n'est trouvée, mais cela fera l'affaire pour le moment.) _

Mais cela échouera probablement dans certaines situations, s'il y a plus d'une iframe, c'est donc juste pour éviter de rester bloqué. Une meilleure solution serait d'appeler manuellement setup et teardown dans mon propre code en passant simplement un paramètre target pour lier et délier les écouteurs.

Merci d'avoir expliqué votre solution, j'améliorerai certainement mes relations publiques si je trouvais une meilleure solution de contournement dans un avenir proche. :)

Hé les gars, je viens de rencontrer ce problème moi-même, je ne peux pas comprendre comment connecter la fenêtre avec iframe. Par exemple, je veux avoir du DragSource sur la fenêtre et je veux créer du DropTarget sur iframe, même si je modifie HTML5Backend, je ne peux pas le faire fonctionner comme ça ...

@mattconde Merci d'avoir partagé ceci. Je suis en train de construire un produit final similaire, je pense. Le pire, c'est que nous utilisons Angular 2. J'ai porté react-dnd sur Angular partiellement, mais finalement, j'ai frappé le mur avec iframe. Je vais essayer votre chemin.

@gaearon Les PR ici ☝️ permettent à react-dnd de prendre en charge les iframes. Si vous avez des inquiétudes ou avez besoin que je change quoi que ce soit, faites-le moi savoir.

@kesne Êtes-vous le nouveau responsable? Pouvez-vous revoir ces PR?

Salut @darthtrevino
Vos modifications permettent-elles de faire glisser un élément de la page vers un cadre?
Je peux glisser-déposer à l'intérieur du cadre et à l'extérieur.

Hey @crysislinux , je cherche à porter cette bibliothèque vers Angular 2 et j'aimerais voir ce que vous avez proposé. Seriez-vous prêt à partager votre code? Merci!

existe-t-il un moyen de déposer des éléments qui sont en dehors de l'iframe à l'intérieur de l'iframe par exemple:

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

Après de nombreux essais, j'ai réussi à déposer des éléments à l'intérieur d'une iframe comme celle-ci:

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>

Cela semble-t-il être la bonne façon de procéder?

J'ai également des problèmes avec l'utilisation de dnd dans une iframe (aucune interaction parentale). Le glisser fonctionne bien, mais les zones de dépôt ne fonctionnent plus. Quelle est la solution pour faire fonctionner les zones de dépôt dans une iframe (il suffit de déplacer l'élément entièrement à l'intérieur de l'iframe).

Je tiens à souligner que cela fonctionne avec le backend Touch mais pas avec le backend HTML5.

Cette page vous a été utile?
0 / 5 - 0 notes