如何防止react js和react-beautiful-dnd中的原始容器下降?

时间:2018-11-10 20:56:24

标签: javascript reactjs drag-and-drop

我正在使用React和react-beautiful-dnd。

这让我感到难过

我的用例是将项目从container1拖到container2。

  1. Container1中的项目不能仅在Container 2中放置在Container 1中。
  2. 如果容器1中的某个项目正在拖动,则容器1中的其余项目不应移动以允许放置。

我创建了一个样本小提琴来隔离用例-https://codesandbox.io/s/34z92ny69p

感谢您的帮助

G

1 个答案:

答案 0 :(得分:1)

如果我了解您想要什么:

  • 允许将Container 1个项目移到Container 2中。
  • 不允许Container 1为空。
  • 不允许将任何项目移回Container 1

可选:我也对其进行了设置,以便您可以通过将isDragDisabled中的DroppableContainer道具向下传递来禁用拖动,例如:

<DroppableContainer
  droppableId="Container2"
  title="Container 2"
  data={this.state.container2Data}
  isDragDisabled
/>

工作示例:https://codesandbox.io/s/moy02o60yx

components / Workspace.js

import React, { Component } from "react";
import { DragDropContext } from "react-beautiful-dnd";
import { Grid, Row } from "react-bootstrap";
import DroppableContainer from "./DroppableContainer";

const testData = {
  container1Data: [
    { id: 1, name: "item 1" },
    { id: 2, name: "item 2" },
    { id: 3, name: "item 3" },
    { id: 4, name: "item 4" },
    { id: 5, name: "item 5" },
    { id: 6, name: "item 6" }
  ],
  container2Data: [
    { id: 101, name: "other item 1" },
    { id: 102, name: "other item 2" }
  ]
};

export default class Workspace extends Component {
  state = {
    container1Data: testData.container1Data,
    container2Data: testData.container2Data
  };

  onDragEnd = ({ destination, source }) => {
    if (
      !destination ||
      destination.droppableId !== "Container2" ||
      (destination.droppableId === source.droppableId &&
        destination.index === source.index)
    ) {
      return;
    }

    this.setState(prevState => {
      const addItem = prevState.container1Data.splice(source.index, 1);
      prevState.container2Data.splice(destination.index, 0, ...addItem);

      return {
        container1Data: [...prevState.container1Data],
        container2Data: [...prevState.container2Data]
      };
    });
  };

  render = () => (
    <DragDropContext onDragEnd={this.onDragEnd}>
      <Grid bsClass="box-container">
        <Row>
          <DroppableContainer
            droppableId="Container1"
            title="Container 1"
            data={this.state.container1Data}
            dropDisabled
          />
          <DroppableContainer
            droppableId="Container2"
            title="Container 2"
            data={this.state.container2Data}
          />
        </Row>
      </Grid>
    </DragDropContext>
  );
}

components / DroppableContainer.js

import React, { PureComponent } from "react";
import { Droppable } from "react-beautiful-dnd";
import { Col } from "react-bootstrap";
import styled from "styled-components";
import DraggableItem from "./DraggableItem";

const StyledDiv = styled.div`
  border: 1px solid #000080;
  padding: 15px;
`;

export default class DroppableContainer extends PureComponent {
  renderDraggableItems = () =>
    this.props.data.map((item, i) => (
      <DraggableItem
        key={i}
        item={item}
        index={i}
        isDragDisabled={
          this.props.isDragDisabled || this.props.data.length === 1
        }
      />
    ));

  render = () => (
    <Col sm={4}>
      <Droppable
        droppableId={this.props.droppableId}
        isDropDisabled={this.props.dropDisabled || false}
      >
        {provided => (
          <StyledDiv
            className={`container ${this.props.data.length === 1 ? "disabled" : null }`}
            ref={provided.innerRef}
            {...provided.droppableProps}
          >
            <div className="row">
              <div className="col">{this.props.title}</div>
            </div>
            {this.renderDraggableItems()}
            {provided.placeholder}
          </StyledDiv>
        )}
      </Droppable>
    </Col>
  );
}

components / DraggableItem.js

import React from "react";
import { Draggable } from "react-beautiful-dnd";
import { Col } from "react-bootstrap";
import styled from "styled-components";

const DragItemStyled = styled.span`
  text-transform: uppercase;
  outline: none;
  border: 0;
  background-color: ${props => (props.isDragDisabled ? "#d8d8d8" : "#bec7bd")};
  line-height: 32px;
  color: ${props => (props.isDragDisabled ? "#a9a9a9" : "#000080")};
  display: inline-block;
  font-family: Karla, Verdana, sans-serif;
  font-size: 14px;
  padding-left: 15px;
  padding-right: 10px;
  cursor: ${props => (props.isDragDisabled ? "no-drop" : "grab")};
  border-radius: 5px;
  margin-bottom: 5px;
  width: 150px;
`;

const DraggableItem = ({ item, index, isDragDisabled }) => (
  <Draggable
    key={item.id}
    draggableId={JSON.stringify({
      nodeId: item.id,
      type: "DragItem"
    })}
    index={index}
    isDragDisabled={isDragDisabled}
  >
    {provided => (
      <div
        className="row"
        {...provided.draggableProps}
        {...provided.dragHandleProps}
        ref={provided.innerRef}
      >
        <Col md={4}>
          <DragItemStyled isDragDisabled={isDragDisabled}>
            {item.name}
          </DragItemStyled>
        </Col>
      </div>
    )}
  </Draggable>
);

export default DraggableItem;