Shane Davis
Shane Davis

Reputation: 952

Why won't "draggable = 'true'" work on React rendered component?

this is driving me mad and hope someone might be able to help.

I have this React.Component:

var Vehicle = React.createClass({
    ondragend: function(e) {
      e.preventDefault();
      // Logic here
        console.log('onDragOver');
    },
    ondragstart: function(e){
      e.preventDefault();
      console.log('ondragstart');
    },
    render: function() {
    that = this
    var loads = this.props.truck.map(function(load , i){
        load.truckid = i
        return (
                <tr key={i} draggable="true" dragstart={that.ondragstart} dragend={that.ondragend}>
                    <td>
                        {load.load_number}
                    </td>
                    <td>
                        {load.stops[0].location_name}
                    </td>
                    <td>
                        {load.stops[1].location_name}
                    </td>
                </tr>
        )
    })
    return (
            <div className="panel panel-primary" draggable="true">
                <VehiclePanelHeading vehicleNbr={this.props.vehicleNbr}></VehiclePanelHeading>
                <div className="panel-body" >
                    <table className="table">
                        <tbody>
                            {loads}
                        </tbody>
                    </table>
                </div>
            </div>
    )

} });

As you can see, I am trying to make the s draggable. Unfortunetly, this won't work, even if I use the Chrome dev tools to manually add this into the html in the browser.

I have tried removing my link to Bootstrap incase this is something to do with the CSS rules, and also tried to render just a html table with no dynamic values.

I can't see how the code in this fiddle:

jsFiddle

Works by setting the draggable=true in the render function, but mine won't.

Thanks in advance for any help.

Edit Added the dropEnd/Start handlers but no change.

Curiously, if I add draggable=true to the div.panel container, this is draggable whilst the containing s remain not.

top level container is draggable

Update

If I create a quick .html page with this table:

                       <table className="table">
                        <thead>
                            <tr>
                                <td>Name</td>
                                <td>Tangyness</td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr draggable="true">
                                <td>Apple</td>
                                <td>4</td>
                            </tr>
                            <tr draggable="true">
                                <td>Orange</td>
                                <td>7</td>
                            </tr>
                        </tbody>
                    </table>

Then the desired draggble = true works on the table rows. However, if I paste this into the React render function:

        return (
            <div className="panel panel-primary" >
                <VehiclePanelHeading vehicleNbr={this.props.vehicleNbr}></VehiclePanelHeading>
                <div className="panel-body" >
                    <table className="table">
                        <thead>
                            <tr>
                                <td>Name</td>
                                <td>Tangyness</td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr draggable="true">
                                <td>Apple</td>
                                <td>4</td>
                            </tr>
                            <tr draggable="true">
                                <td>Orange</td>
                                <td>7</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
    )

Then suddenly, the 'draggability' is lost.

Upvotes: 3

Views: 15611

Answers (2)

Daniel Kim
Daniel Kim

Reputation: 1025

The reason that the item doesn't seem to drag is you have e.preventDefault(); inside onDragStart function, which prevents it from showing the default dragging movement. Just remove that line, so it would look like this and it should work:

var Vehicle = React.createClass({
  ...
  onDragStart: function(e){
    // REMOVED THIS LINE
    //e.preventDefault();

    console.log('ondragstart');
  },
  ...

Upvotes: 1

AndersNS
AndersNS

Reputation: 1607

It should work, but you probably want to implement onDragOver event(s) too. Otherwise it will look like it doesn't work because you can drag your component, but don't have any legal place to drop it. onDragOver lets you specify if an element accepts dropping and which elements it accepts.

As you can see in the fiddle you linked there are onDragOver events which look something like this

onDragOver: function(e) {
    e.preventDefault();
    // Logic here
}

Calling e.preventDefault(); tells the browser that dropping is possible here. You can put the onDragOver event on any of your parent elements, or on the tr itself. You can read more about drop targets here. If you remove the onDragOver event from the jsFiddle you linked the code in the fiddle stops functioning too.

If you implement onDragOver you will be able to implement an onDrop event on your table that handles dropped tr elements.

Here is your code with the events implemented:

var Vehicle = React.createClass({
    onDragOver: function(e) {
      e.preventDefault();
      // Logic here
      console.log('onDragOver');
    },
    onDragStart: function(e){
        e.dataTransfer.setData('id', 'setTheId');
        console.log('onDragStart');
    },
    onDrop: function(e) {
        console.log('onDrop');
        var id = event.dataTransfer.getData('id');
        console.log('Dropped with id:', id);
    },
    render: function() {
        that = this;
        var loads = this.props.truck.map(function(load , i){
            load.truckid = i
            return (

                    <tr key={i} draggable="true" onDragOver={that.onDragOver} onDragStart={that.onDragStart}>
                        <td>
                            {load.load_number}
                        </td>
                        <td>
                            {load.stops[0].location_name}
                        </td>
                        <td>
                            {load.stops[1].location_name}
                        </td>
                    </tr>

            )
        })
        return (
                <div>
                    <div className="panel-body" >
                        <table className="table" onDrop={this.onDrop}>
                            <tbody>
                                {loads}
                            </tbody>
                        </table>
                    </div>
                </div>
        )
    } 
});

Here is a jsFiddle of this: http://jsfiddle.net/kb3gN/10761/

Upvotes: 4

Related Questions