Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble with drag-and-drop sortable list using ReactJs and react-dnd

Using ReactJs and react-dnd

I want a user to be able to sort the form fields (a.k.a. properties)

I set up the code almost identical to the source code for the Cards in the simple sort demo. There are no console warnings or errors, and I can't figure out why this won't work. I can neither drag nor drop anything.

What it looks like:

Example dummy-seeded form

Code:

App.js

import EditForm from './Forms/EditForm.js';

var id = $('#form').data('id');
var source = `/api/forms/${id}?include=type,properties.type`;

React.render(
    <EditForm source={source} />,
    document.getElementById('form')
);

EditForm.js

import React from 'react/addons';
import update from 'react/lib/update';
import Property from './Property.js';

var EditForm = React.createClass({

    mixins: [ React.addons.LinkedStateMixin ],

    getInitialState: function() {
        return {
            id: null,
            name: null,
            slug: null,
            properties: []
        }
    },

    componentDidMount: function() {
        this.getFormFromServer();
    },

    getFormFromServer: function () {
        $.get(this.props.source, (result) => {
            if (this.isMounted()) {
                this.setState({
                    id: result.id,
                    name: result.name,
                    slug: result.slug,
                    properties: result.properties.data
                });
            }
        });
    },

    moveProperty: function(id, afterId) {
        const { properties } = this.state;

        const property = properties.filter(p => p.id === id)[0];
        const afterProperty = properties.filter(p => p.id === afterId)[0];
        const propertyIndex = properties.indexOf(property);
        const afterIndex = properties.indexOf(afterProperty);

        this.setState(update(this.state, {
            properties: {
                $splice: [
                    [propertyIndex, 1],
                    [afterIndex, 0, property]
                ]
            }
        }));
    },

    render: function() {
        const { properties } = this.state;

        var propertiesList = properties.map((property, i) => {
            return (
                <Property
                    key={property.id}
                    id={property.id}
                    type={property.type.name}
                    name={property.name}
                    moveProperty={this.moveProperty} />
            );
        });

        return (
            <div>
                <h1>Form</h1>
                <form>
                    <div className="form-group">
                        <label>Name:</label>
                        <input type="text" name="name" valueLink={this.linkState('name')} className="form-control" />
                    </div>
                    <div className="form-group">
                        <label>Properties:</label>
                        <div className="list-group properties-list">
                            {propertiesList}
                        </div>
                    </div>
                </form>
            </div>
        );
    }

});

export default EditForm;

Property.js

import React, { PropTypes } from 'react/addons';
import { DragDropMixin } from 'react-dnd';
import ItemTypes from './ItemTypes';

const dragSource = {
    beginDrag(component) {
        return {
            item: {
                id: component.props.id
            }
        };
    }
};

const dropTarget = {
    over(component, item) {
        component.props.moveProperty(item.id, component.props.id);
    }
};

var Property = React.createClass({

    mixins: [ React.addons.LinkedStateMixin, DragDropMixin ],

    propTypes: {
        id: PropTypes.any.isRequired,
        type: PropTypes.string.isRequired,
        name: PropTypes.string.isRequired,
        moveProperty: PropTypes.func.isRequired
    },

    statics: {
        configureDragDrop(register) {
            register(ItemTypes.PROPERTY, {
                dragSource,
                dropTarget
            });
        }
    },

    render: function () {
        const { type } = this.props;
        const { name } = this.props;
        const { isDragging } = this.getDragState(ItemTypes.PROPERTY);
        const opacity = isDragging ? 0 : 1;

        return (
            <a  className="list-group-item"
                {...this.dragSourceFor(ItemTypes.PROPERTY)}
                {...this.dropTargetFor(ItemTypes.PROPERTY)}>
                {type}: {name}
            </a>
        );
    }
});

export default Property;

ItemTypes.js

module.exports = {
    PROPERTY: 'property'
};

If anybody could help I would greatly appreciate it. It's kind of sad how much time I've actually spent trying to figure this out.

Reference links:

  • My code on github
  • Demo example
  • Demo source on github
like image 672
ryanwinchester Avatar asked Nov 10 '22 15:11

ryanwinchester


1 Answers

After spending over a day trying to get the drag and drop working I fixed it with one single line of code.

import React from 'react/addons';

How it compiled and rendered at all without that, I don't even know.

like image 170
ryanwinchester Avatar answered Nov 14 '22 21:11

ryanwinchester