Реагировать Dnd вне позиции после прокрутки

Я использую react-beautiful-dnd, чтобы сделать строки таблицы перетаскиваемыми.
Перетаскивание работает нормально, если я иду сверху вниз, и когда я прокручиваю страницу вверх, она выходит из положения.
Я понятия не имею, почему. Также я не нашел ничего странного в css

Я понятия не имею, почему это происходит, и не знаю, как это исправить. Вот пример моей проблемы.

Реагировать Dnd вне позиции после прокрутки

Это мой код:

import update from "immutability-helper";
import * as React from "react";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import { WithNamespaces, withNamespaces } from "react-i18next";
import { toastr } from "react-redux-toastr";
import * as HttpHelper from "../../httpHelper";
import { FormState } from "../common/ValidatedForm";
type Props = WithNamespaces & {
  id: number;
  displayName: string;
  type: string;
  language: any;
};

interface Fields {
  columns: any;
}

type State = FormState<Fields> & {
  isLoading: boolean,
  canSave: boolean,
  isSaving: boolean,
  possibleTags: any,
  configTagModalActive: boolean,
  previewModalActive: boolean,
  activeTag: any
};
const getItemStyle = (isDragging: any, draggableStyle: any) => ({
  ...draggableStyle,
  opacity: isDragging ? 1 : 1,
  boxShadow: "0px 0px 0px 1px #8b8b8b",
});
const shadowColor = "#a0a0a057";
const Column = (props: any) => {
  function findindex(val: any, pt: any) {
    const list = pt ? props.possibleTags : props.tags;
    return list.findIndex((item: any) => val == item.name);
  }
  function findindexofhelptext(val: any, pt: any) {
    const list = pt;
    return list.findIndex((item: any) => val == item.language);
  }
  return (
    <tr ref = {props.provided.innerRef} {...props.provided.draggableProps} style = {getItemStyle(props.snapshot.isDragging, props.provided.draggableProps.style)} className = {"draggablerow " + (props.snapshot.isDragging ? "draggedrow" : "") } key = {props.indexnr} data-id = {props.index} >
      <td {...props.provided.dragHandleProps} style = {{width: "50px", textAlign: "center", cursor: "move"}}><i className = "fa fa-bars" style = {{lineHeight: "40px", fontSize: "24px"}}></i></td>
      <td style = {{ textAlign: "center", width: "100px" }}>
        <input
          type = "checkbox"
          className = "flipswitch"
          id = {props.index}
          checked = {props.export}
          onChange = {props.toggleVisible}
        />
      </td>
      <td style = {{width: "350px" }}>
        <input
          type = "text"
          name = "caption"
          id = {props.index}
          className = "form-control"
          value = {props.caption}
          onChange = {props.onTextUpdate}
          style = {{boxShadow: "2px 2px 3px 1px" + shadowColor}}
        />
      </td>
      <td style = {{width: "350px" }}>
        <input
          type = "text"
          name = "fieldname"
          id = {props.index}
          className = "form-control"
          value = {props.fieldname}
          onChange = {props.onTextUpdate}
          style = {{boxShadow: "2px 2px 3px 1px" + shadowColor}}
        />
      </td>
      <td style = {{width: "400px"}}>
        <div className = "tags-input" style = {tagInputStyle}>
          {Object.keys(props.tags).map((key, i) =>
            <div key = {i} className = "tag" onClick = {props.onConfigButtonClicked} data-id = {i} data-parent = {props.index}>
              {props.tags[i].name} <i className = "fa fa-trash" id = {props.index} data-key = {i} data-name = {props.tags[i].name} onClick = {props.onDeleteTag} style = {{float: "right"}} ></i>
            </div>
          )}
        </div>
      </td>
      <td style = {{ textAlign: "center", width: "100px" }}>
        <button onClick = {() => props.onDeleteColumn(props.index)} type = "button" style = {{padding : "8px 16px", boxShadow: "2px 2px 2px 1px" + shadowColor }} className = "btn btn-danger btn-rounded"><i className = "fa fa-trash"></i></button>
      </td>
      </tr>
  );
};
const reorder = (list: any, startIndex: any, endIndex: any) => {
  const result = Array.from(list);
  const [removed] = result.splice(startIndex, 1);
  result.splice(endIndex, 0, removed);
  return result;
};
interface SetColumnsResponse extends HttpHelper.ResponseData { columns: any; }

class CrmConnectorColumns extends React.Component<Props, State> {

  constructor(props: Props) {
    super(props);
    this.moveColumn = this.moveColumn.bind(this);
    this.state = {
      isLoading: true,
      isSaving: false,
      canSave: false,
      errorColor: "danger",
      fields: { columns: [] },
      deleteModalActive: false,
      configTagModalActive: false,
      previewModalActive: false,
      activeTag: {name: "", attributes: [{name: "", value: ""}]},
      possibleTags: [
        {name: "PRIMARY", status: "new", helptexts: [
          {language: "nl", helptext: "Dit is de primary key"},
          {language: "en", helptext: "This is the primary key"}
        ], attributes: [], uses: 1},
        {name: "SUBTITLE", status: "new", helptexts: [
          {language: "nl", helptext: "Dit is de subtitel van een record"},
          {language: "en", helptext: "This is The subtitle of a record"}
        ], attributes: [], uses: 1},
        {name: "URL", status: "new", helptexts: [
          {language: "nl", helptext: "De waarde wordt gezien als link."},
          {language: "en", helptext: "The value becomes a link."}
        ], attributes: [
          {name: "link", status: "new", helptexts: [
            {language: "nl", helptext: "De link krijgt deze waarde. Voorbeeld waarde is \"http://www.google.nl?search=[naam]\". de waarde van \"[naam]\" wordt ingevuld."},
            {language: "en", helptext: "The link gets this value. Example value is \"http://www.google.nl?search=[name]\". the value of \"[name]\" gets filled in."}
          ]}
        ], uses: undefined},
        {name: "TITLE", status: "new", helptexts: [
          {language: "nl", helptext: "Dit is de hoofdtitel van een record"},
          {language: "en", helptext: "This is the maintitle of a record"}
        ], attributes: [], uses: 1},
        {name: "PHONE", status: "new", helptexts: [
          {language: "nl", helptext: "De waarde wordt gezien als telefoonnummer"},
          {language: "en", helptext: "The value becomes a phonenumber"}
        ], attributes: [], uses: undefined},
        {name: "BUTTON", status: "new", helptexts: [
          {language: "nl", helptext: "Uiterlijk van een knop"},
          {language: "en", helptext: "The value becomes a button"}
        ], attributes: [], uses: undefined},
        {name: "EMAIL", status: "new", helptexts: [
          {language: "nl", helptext: "De waarde wordt gezien als e-mail adres"},
          {language: "en", helptext: "The value becomes a emailaddress"}
        ], attributes: [], uses: undefined},
        {name: "IMAGE", status: "new", helptexts: [
          {language: "nl", helptext: "De waarde wordt als afbeelding weergegeven"},
          {language: "en", helptext: "The value gets displayed as image"}
        ], attributes: [], uses: undefined},
        {name: "HTML", status: "new", helptexts: [
          {language: "nl", helptext: "De waarde wordt gezien als HTML"},
          {language: "en", helptext: "The value gets seen as custom HTML"}
        ], attributes: [
          {name: "HTML code", status: "new", helptexts: [
            {language: "nl", helptext: "Vul hier je custom HTML code in. De waarde tussen de [] word vervangen door de data."},
            {language: "en", helptext: "Enter your custom HTML here. The value between the [] will be replaced for the value."}
          ]}
        ], uses: undefined}
      ]
    };
    this.onDragEnd = this.onDragEnd.bind(this);
  }
  onDragEnd(result: any) {
    // dropped outside the columns table
    if (!result.destination) {
      return;
    }
    let newlist = [...this.state.fields.columns];
    newlist = reorder(
      newlist,
      result.source.index,
      result.destination.index
    );
    Object.keys(newlist).forEach((nr) => {
      newlist[parseInt(nr, 10)].index = parseInt(nr, 10);
    });
    this.setState({ fields: { columns: newlist } });
    this.setState({ canSave: true });
  }
  async componentDidMount() {
    console.info("Start select columns");
    const fields = await HttpHelper.getJson<Fields>(`/${this.props.type}/${this.props.id}/columns`);
    this.setState(prevState => {
      return update(prevState, {
        fields: { $set: fields },
        isLoading: { $set: false },
      });
    });
    if (this.state.fields.columns == undefined) {
      this.setState({ fields: { columns: [] } });
    }
    for (let i = 0; i < fields.columns.length; i++) {
      fields.columns[i].index = i;
    }
    this.setState({ fields: { columns: fields.columns } });
    const newlist = [...this.state.possibleTags];

    for (const column of fields.columns) {
      for (const tags of column.tags) {
        const index = newlist.map((item) => item.name).indexOf(tags.name);
        if (newlist[index].uses > 0) {
          newlist[index].uses = 0;
        }
      }
    }
    this.setState({ possibleTags: newlist });
  }
  moveColumn(index: any, indexnr: any) {
    const cards = this.state.fields.columns;
    const sourceCard = cards.find((card: any) => card.index === index);
    const sortCards = cards.filter((card: any) => card.index !== index);
    sortCards.splice(indexnr, 0, sourceCard);
     Object.keys(sortCards).forEach((nr) => {
    sortCards[nr].index = parseInt(nr, 10);
    });
    this.setState({ fields: { columns: sortCards } });
    this.setState({ canSave: true });
  }

  onDragStart = (e: any) => {
    e.dataTransfer.effectAllowed = "move";
    e.dataTransfer.setData("text/html", e.target.parentNode);
    e.dataTransfer.setDragImage(e.target.parentNode, 20, 20);
  }
  ondragOver(e: any) {
    e.preventDefault();
  }

  public render() {
    const columns = this.state.fields.columns || [] ;
    const { t } = this.props;
    let placeholder: any;

    if (columns.length < 1) {
      placeholder = <tr style = {{boxShadow: "0px 0px 0px 1px #8b8b8b", textAlign: "center"}} className = {"draggablerow"}><td colSpan = {6} >{t("placeholder")}</td></tr>;
    }
    return (
      <form>
        <div className = "App">
          <main>
            <button onClick = {this.onSubmit} className = "btn btn-primary" type = "submit" style = {{float: "right", boxShadow: "2px 2px 3px 1px" + shadowColor}} disabled = {!this.state.canSave || this.state.isSaving}>{this.state.isSaving ? <i className = "fa fa-spinner fa-spin"></i> : ""} {this.props.t("update")}</button>
            <button onClick = {this.onPreviewButtonClicked} type = "button" className = "btn btn-primary"  style = {{float: "right", boxShadow: "2px 2px 3px 1px" + shadowColor, marginRight: "5px"}} >Preview</button><br/><br/>
            <DragDropContext onDragEnd = {this.onDragEnd}>
              <table className = "col-8 table columns" style = {{tableLayout: "auto"}} >
                <thead className = "" style = {{border: "2px solid #1b2847", background: "#1b2847", color: "white"}}>
                  <tr>
                    <th colSpan = {2} style = {{textAlign: "center"}}>
                      <button onClick = {this.onAddColumn} disabled = {columns.length > 14 ? true : false} type = "button" style = {{padding : "8px 16px", boxShadow: "2px 2px 3px 1px" + shadowColor }} className = "btn btn-primary btn-rounded"><i className = "fa fa-plus"></i> </button>
                    </th>
                    <th>{t("displayname")}</th>
                    <th>Element</th>
                    <th>Tags</th>
                    <th></th>
                  </tr>
                </thead>
                <Droppable droppableId = "droppable" direction = "vertical">
                  {(provided: any) => (
                    <tbody  ref = {provided.innerRef}>
                      {Object.keys(columns).map((element, key) => (
                        <Draggable key = {"draggable" + key} draggableId = {element} index = {key}>
                        {(provided, snapshot) => (
                          <Column
                          key = {"column" + key}
                          indexnr = {key}
                          toggleVisible = {this.toggleVisible}
                          onTextUpdate = {this.onTextUpdate}
                          onDeleteColumn = {this.onDeleteColumn}
                          onDeleteTag = {this.onDeleteTag}
                          onAddTag = {this.onAddTag}
                          possibleTags = {this.state.possibleTags}
                          onConfigButtonClicked = {this.onConfigButtonClicked}
                          onPreviewButtonClicked = {this.onPreviewButtonClicked}
                          onClosePreview = {this.onClosePreview}
                          provided = {provided}
                          snapshot = {snapshot}
                          language = {this.props.language}
                          {...columns[key]}
                          />
                        )}
                        </Draggable>
                      ))}
                      {provided.placeholder}
                     </tbody>
                  )}
                </Droppable>
              </table>
            </DragDropContext>
          </main>
        </div>

      </form>
    );
  }
}
export default withNamespaces(["crmConnectorColumns", "Common"])(CrmConnectorColumns);

Я надеюсь, что кто-нибудь сможет узнать, почему мой перетаскиваемый элемент выходит из положения, когда я прокручиваю страницу вниз.

Можете добавить пример в codeandbox со статическими данными? Я попытался добавить пример, но в коде импортированы отсутствующие файлы.

Special Character 03.04.2019 01:44

Я создал чрезвычайно простой пример с ядром вашего кода здесь: codeandbox.io/s/my64446wl9 Я не видел тех же результатов, что и вы, поэтому я готов поспорить, что где-то переопределяются стили.

Special Character 03.04.2019 01:59

Разные версии браузера? Попробуйте также в режиме инкогнито, если вы получаете те же результаты (иногда расширения могут мешать странице)

bsekula 04.04.2019 22:43

Возможно, ваши перетаскиваемые элементы имеют прокрутку переполнения. Возможно, попробуйте установить overflow-y: hidden для перетаскиваемых элементов.

Jake 04.04.2019 23:20

Итак, при прокрутке некоторые стили переопределяются?

Jbadminton 05.04.2019 11:46

Можете ли вы разместить воспроизводимый пример где-нибудь?

Dehan 06.04.2019 05:56

у меня нет, только на моем локальном хосте

user10960236 08.04.2019 16:56

setDragImage, yOffset должен меняться при перетаскивании вверх и при перетаскивании вниз.

VariableVasasMT 16.04.2019 13:56
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
17
8
5 519
3

Ответы 3

Возможно, для ответа уже поздно, но для кого-то он может быть полезен. Если вы посмотрите ближе, вы увидите смещение при прокрутке, и это причина неработающих стилей. Для решения вам следует подумать о контейнере прокрутки, если вы добавляете прокрутку в HTMLElement, а не в окно, вам нужно проверить этот пример. Эта проблема связана с самим react-beautiful-dnd, и обновленная версия исправит это.

Я столкнулся с той же проблемой. Проблема для меня заключалась в том, что droppable(list) находился внутри, например, контейнера основной, который можно было прокручивать (т.е. переполнять: прокручивать).

Я решил проблему преобразование droppable в прокручиваемый вместоосновнойконтейнер

Пример с проблемой

.main {
  background: #eee;
  padding: 3rem;
  height: 200px;
  overflow-y: scroll;
}
.droppable {
  padding: 1rem;
  background: #aaa;
}
.draggable {
  margin: 0.5rem 0;
  padding: 1rem;
  background: #ccc;
}
<div class = "main">
  <div class = "droppable">
    <div class = "draggable">
        <span class = "text"> item</span>
    </div>
      <div class = "draggable">
          <span class = "text"> item</span>
    </div>
      <div class = "draggable">
        <span class = "text"> item</span>
    </div>
  </div>
</div>

Пример с решенной проблемой

.main {
  background: #eee;
  padding: 3rem;
  height: 200px;
}
.droppable {
  padding: 1rem;
  background: #aaa;
  height: 180px;
  overflow-y: scroll;
}
.draggable {
  margin: 0.5rem 0;
  padding: 1rem;
  background: #ccc;
}
<div class = "main">
  <div class = "droppable">
    <div class = "draggable">
        <span class = "text"> item</span>
    </div>
      <div class = "draggable">
          <span class = "text"> item</span>
    </div>
      <div class = "draggable">
        <span class = "text"> item</span>
    </div>
  </div>
</div>

Изменения были внесены только в CSS, чтобы сделать выпадающий контейнер короче, чем контейнер основной, и добавлено overvlow-y:scroll к выпадающему

Я также столкнулся с той же проблемой.

Единственная работа, которую я нашел, это

*Фиксация высоты элемента при вертикальном перетаскивании. *Фиксация ширины элемента при горизонтальном перетаскивании.

Также еще одна вещь, которую следует упомянуть, устанавливает свойство отображения элемента, перетаскиваемого в блок.

Пример кода требуемого CSS был бы полезен здесь

cody.codes 18.02.2022 00:01

Другие вопросы по теме