首页 > 解决方案 > 调整大小功能似乎与外部拖放不兼容

问题描述

首先,我想对这个 repo 表示感谢:https ://github.com/Tim1023/react-scheduler-firebase没有它我将无法为 react-big- 实现外部拖放日历。

我花了整整一周的时间尝试玩这些东西,但是调整大小功能(向上和向下拉伸事件)对它不起作用。我想问题出在 css 上?我尝试将 react-big-calendar 的版本从0.19to升级0.20,情况正好相反 - 调整大小工作正常,但外部 DnD 不再工作(即,在日历上拖动外部对象时,放置模式不会被激活)

关于这个有一个未解决的问题,但看起来它到目前为止仍未处理。

标签: react-dndreact-big-calendar

解决方案


最新版本的 RBC 确实包含外部拖放功能。尽管文档站点尚未更新,但克隆 repo 并运行“示例”将显示此功能的工作演示。这是该演示的来源:

import React from 'react'
import events from '../events'
import { Calendar, Views } from 'react-big-calendar'
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'
import Layout from 'react-tackle-box/Layout'
import Card from '../Card'

import 'react-big-calendar/lib/addons/dragAndDrop/styles.scss'

const DragAndDropCalendar = withDragAndDrop(Calendar)

const formatName = (name, count) => `${name} ID ${count}`

class Dnd extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      events: events,
      draggedEvent: null,
      counters: {
        item1: 0,
        item2: 0,
      },
      displayDragItemInCell: true,
    }
  }

  handleDragStart = event => {
    this.setState({ draggedEvent: event })
  }

  handleDisplayDragItemInCell = () => {
    this.setState({
      displayDragItemInCell: !this.state.displayDragItemInCell,
    })
  }

  dragFromOutsideItem = () => {
    return this.state.draggedEvent
  }

  customOnDragOver = event => {
    // check for undroppable is specific to this example
    // and not part of API. This just demonstrates that
    // onDragOver can optionally be passed to conditionally
    // allow draggable items to be dropped on cal, based on
    // whether event.preventDefault is called
    if (this.state.draggedEvent !== 'undroppable') {
      console.log('preventDefault')
      event.preventDefault()
    }
  }

  onDropFromOutside = ({ start, end, allDay }) => {
    const { draggedEvent, counters } = this.state
    const event = {
      title: formatName(draggedEvent.name, counters[draggedEvent.name]),
      start,
      end,
      isAllDay: allDay,
    }
    const updatedCounters = {
      ...counters,
      [draggedEvent.name]: counters[draggedEvent.name] + 1,
    }
    this.setState({ draggedEvent: null, counters: updatedCounters })
    this.newEvent(event)
  }

  moveEvent = ({ event, start, end, isAllDay: droppedOnAllDaySlot }) => {
    const { events } = this.state

    const idx = events.indexOf(event)
    let allDay = event.allDay

    if (!event.allDay && droppedOnAllDaySlot) {
      allDay = true
    } else if (event.allDay && !droppedOnAllDaySlot) {
      allDay = false
    }

    const updatedEvent = { ...event, start, end, allDay }

    const nextEvents = [...events]
    nextEvents.splice(idx, 1, updatedEvent)

    this.setState({
      events: nextEvents,
    })

    // alert(`${event.title} was dropped onto ${updatedEvent.start}`)
  }

  resizeEvent = ({ event, start, end }) => {
    const { events } = this.state

    const nextEvents = events.map(existingEvent => {
      return existingEvent.id == event.id
        ? { ...existingEvent, start, end }
        : existingEvent
    })

    this.setState({
      events: nextEvents,
    })

    //alert(`${event.title} was resized to ${start}-${end}`)
  }

  newEvent = event => {
    let idList = this.state.events.map(a => a.id)
    let newId = Math.max(...idList) + 1
    let hour = {
      id: newId,
      title: event.title,
      allDay: event.isAllDay,
      start: event.start,
      end: event.end,
    }
    this.setState({
      events: this.state.events.concat([hour]),
    })
  }

  render() {
    return (
      <div>
        <Card className="examples--header" style={{ display: 'flex' }}>
          <div
            style={{
              display: 'flex',
              flex: 1,
              justifyContent: 'center',
              flexWrap: 'wrap',
            }}
          >
            <h4 style={{ color: 'gray', width: '100%' }}>
              Outside Drag Sources
            </h4>
            {Object.entries(this.state.counters).map(([name, count]) => (
              <div
                style={{
                  border: '2px solid gray',
                  borderRadius: '4px',
                  width: '100px',
                  margin: '10px',
                }}
                draggable="true"
                key={name}
                onDragStart={() =>
                  this.handleDragStart({ title: formatName(name, count), name })
                }
              >
                {formatName(name, count)}
              </div>
            ))}
            <div
              style={{
                border: '2px solid gray',
                borderRadius: '4px',
                width: '100px',
                margin: '10px',
              }}
              draggable="true"
              key={name}
              onDragStart={() => this.handleDragStart('undroppable')}
            >
              Draggable but not for calendar.
            </div>
          </div>

          <div>
            <label>
              <input
                style={{ marginRight: 5 }}
                type="checkbox"
                checked={this.state.displayDragItemInCell}
                onChange={this.handleDisplayDragItemInCell}
              />
              Display dragged item in cell while dragging over
            </label>
          </div>
        </Card>
        <DragAndDropCalendar
          selectable
          localizer={this.props.localizer}
          events={this.state.events}
          onEventDrop={this.moveEvent}
          dragFromOutsideItem={
            this.state.displayDragItemInCell ? this.dragFromOutsideItem : null
          }
          onDropFromOutside={this.onDropFromOutside}
          onDragOver={this.customOnDragOver}
          resizable
          onEventResize={this.resizeEvent}
          onSelectSlot={this.newEvent}
          onD
          defaultView={Views.MONTH}
          defaultDate={new Date(2015, 3, 12)}
        />
      </div>
    )
  }
}

export default Dnd

推荐阅读