React-Virtualized таблица, чтобы расти до максимальной высоты - PullRequest
0 голосов
/ 12 октября 2018

Проблема: Я хотел бы иметь React Virtualized table , которая может занимать максимальный пробел по высоте (скажем, 500px).Сразу под последней видимой строкой таблицы я хотел бы добавить еще один элемент.Примерно так:

If the content of the table is shorter than 500px

+-----------------------------------------+    ----+
| Header1 | Header2 | ...                 |        |
+---------+---------+---------------------+        |  less than 500px,
| row1    | row1    | row1                |        |  say 200px
+---------+---------+---------------------+        |
| row2    | row2    | row2                |        |
+---------+---------+---------------------+    ----+
Other content


If the content of the table is longer than 500px

+-----------------------------------------+^   ----+
| Header1 | Header2 | ...                 ||       |
+---------+---------+---------------------+|       |  500px,
| row1    | row1    | row1                ||       |  notice the
+---------+---------+---------------------+|       |  scroll bar
| row2    | row2    | row2                ||       |
+---------+---------+---------------------+|       |
| row3    | row3    | row3                ||       |
+---------+---------+---------------------+|       |
| row4    | row4    | row4                |V   ----+
Other content

Другими словами: между таблицей и «другим содержимым» не должно быть белого промежутка, но также таблица должна занимать максимум 500 пикселей.

Вопрос: Как мне этого добиться?

Моя попытка: Я пробовал с AutoSizer , но проблема:

  • , если AutoSizer содержится в div только с фиксированной высотой (например, height: 500px), тогда между таблицей и "Прочим содержимым" будет белый пробел, еслистол слишком короткий;так что я получаю это:

    +-----------------------------------------+    ----+
    | Header1 | Header2 | ...                 |        |
    +---------+---------+---------------------+        |  less than 500px,
    | row1    | row1    | row1                |        |  say 200px
    +---------+---------+---------------------+        |
    | row2    | row2    | row2                |        |
    +---------+---------+---------------------+    ----+
                                                       |
                                                       | gap of        
                                                       | 300px
                                                       |        
                                                       |
    Other content                                  ----+
    
  • , если AutoSizer содержится в div только с максимальной высотой (например: max-height: 500px), то толькоотображается заголовок, а «Другое содержимое» будет выше заголовка (т. е. содержащий div не увеличивается по мере увеличения таблицы, и, таким образом, AutoSizer ничего не делает);то, что я получаю, это:

    Other content ----------------------------+
    | Header1 | Header2 | ...                 |
    +---------+---------+---------------------+
    
  • (Если я даю максимальную и фиксированную высоту, то, конечно, фиксированная высота «выигрывает», и результат такой же, как впервый случай.)

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

Источник для справки:

 <div>
   <div style={{height: "100px", maxHeight: "500px"}}>
      <AutoSizer>
        {({height, width}) => (
          <Table
            ref="Table"
            disableHeader={false}
            headerClassName=""
            headerHeight={40}
            height={height}
            rowClassName=""
            rowHeight={40}
            rowGetter={rowGetter}
            rowCount={6}
            width={width}>
            <Column
                label="Index"
                cellDataGetter={({rowData}) => rowData.index}
                dataKey="index"
                width={60}
            />
            <Column
              label="Text1"
              cellDataGetter={({rowData}) => rowData.text1}
              dataKey="text1"
              width={90}
            />
            <Column
              label="Text2"
              cellDataGetter={({rowData}) => rowData.text2}
              dataKey="text2"
              width={90}
            />
          </Table>
        )}
      </AutoSizer>             
  </div>
  <div>Some other text</div>
 </div>

Обновления

Разъяснение ограничений: Решение должно работать с таблицей Virtualized-React.Это не вариант использовать таблицу HTML.(Выше я только сказал, что, возможно, AutoSizer не является правильным решением, но мне нужна таблица реакции.)

Предлагаемый подход в ответе : я пыталсяприменить предложение @ jered к моему делу, и снова получил таблицу, которая распространяется на всю максимальную высоту.Я не уверен, что сделал что-то не так или предложенный подход вообще не работает для этой ситуации* с размером 0px x 0px и видимым переполнением его содержимого.Таким образом, если размер переполнения может быть рассмотрен, это решит проблему.Сам по себе это интересный вопрос, поэтому я открою продолжение, но оставлю этот вопрос открытым, поскольку для этого конкретного случая может быть лучшее решение.

Еще одно обновление : Я заметил, что div нулевого размера не создается, если я помещаю таблицу внутрь flex-контейнера.

1 Ответ

0 голосов
/ 12 октября 2018

Не нужно прибегать к React или чему-либо сложному.Просто используйте FlexBox на простом CSS.

Дайте контейнер ваших «Таблиц» и «Другой контент» display: flex и установите max-height на внутреннем элементе, который окружает <table>.Дети FlexBox будут пытаться расширяться, чтобы заполнить столько места, сколько требуется их содержимому, но не будут расширяться, но не будут расширяться после их max-height, если установлено.

Примечание. Разверните фрагмент до полного экрана, чтобы увидеть полный эффект.

function adjustrows() {
  let val = document.getElementById("slider").value;
  let table = document.getElementById("table");
  let inner = `
    <tr>
      <th>foo</th>
      <th>bar</th>
      <th>baz</th>
      <th>foo</th>
      <th>bar</th>
      <th>baz</th>
    </tr>
  `;
  for (let i = 0; i < val; i++) {
    inner += `
      <tr>
        <td>foo</td>
        <td>bar</td>
        <td>baz</td>
        <td>foo</td>
        <td>bar</td>
        <td>baz</td>
      </tr>
    `;
  }
  table.innerHTML = inner;
  document.getElementById("numrows").innerText = val;
}
adjustrows();
table, tr, th, td {
  box-sizing: border-box;
  border: 1px solid gray;
}

table {
  flex-grow: 1;
}

th {
  background: lightgray;
}

label {
  display: flex;
  justify-content: center;
  margin: 5px;
}

#numrows {
  margin: 0 10px;
}

#flex-container {
  display: flex;
  border: 1px solid red;
  flex-direction: column;
}

#table-container {
  display: flex;
  max-height: 500px;
  border: 1px solid blue;
  padding: 2px;
  margin: 2px;
  overflow: scroll;
}

#other-content-container {
  display: flex;
  flex-direction: column;
  border: 1px solid green;
  padding: 2px;
  margin: 2px;
}

.placeholder {
  background: darkgray;
  margin: 10px;
  height: 120px;
}
<div id="flex-container">
  <label>
    <strong>Number of table rows:<span id="numrows"></span> </strong>
    <input id="slider" onchange="adjustrows();" oninput="adjustrows();" type="range" min="0" max="100" value="1" />
  </label>
  <div id="table-container">
    <table id="table">
    </table>
  </div>
  <div id="other-content-container">
    <div class="placeholder"></div>
    <div class="placeholder"></div>
    <div class="placeholder"></div>
    <div class="placeholder"></div>
    <div class="placeholder"></div>
  </div>
</div>

Обратите внимание, что при удалении некоторых элементов <tr> из таблицы, так что она короче 500px, #table-container будетпросто уменьшитесь, чтобы приспособиться.

Как всегда, в Mozilla Developer Network есть немного полезной информации о FlexBox.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...