Как я могу динамически изменять размер столбцов таблицы в соответствии с содержимым, выравнивать по левому краю и сохранять максимальную ширину?

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

Это проект VueJS, и я использовал (или в зависимости от того, смогу ли я заставить его работать) Пользовательский интерфейс элемента

Итак, перейдем к деталям. Я хочу, чтобы моя таблица выглядела так:

Header A    Header B                     Header C
------------------------------------------------------------------------------- 100%
Apples      Bananas la la la la la la... A box of crackers and some super ri...
Oranges     Mr. Bean Is Cool             More chocolate milk

Этот пример text-overflow: ellipsis

Или вот так:

Header A    Header B    Header C
------------------------------------------------------------------------------- 100%
Apples      Bananas     A box of crackers and some super rich chocolate milk
Oranges     Mr. Bean    More chocolate milk

Или вот так:

Header A    Header B                      Header C
------------------------------------------------------------------------------- 100%
Apples      Bananas are not my favorite   A box of crackers and some super r...
Oranges     Mr. Bean                      More chocolate milk

Или вот так:

Header A    Header B    Header C
------------------------------------------------------------------------------- 100%
Apples      Bananas     Oranges
Running     Out         Of ideas to put in here

Дело в том, чтобы поля оставались выровненными по левому краю и не распределялись по ширине. Я пробовал различные макеты, такие как table-layout: fixed с и width: auto, и, честно говоря, я перепробовал так много вариантов, что не уверен, какими из них поделиться.

Чтобы усложнить задачу, таблица генерируется динамически из json, и я не знаю, какие столбцы у меня будут или их содержимое. Итак, вот некоторые из предпринятых мною псевдошагов:

// Figure out how many actual columns are visible
let visibleColumns = _.filter(this.$refs.table.columns, c => {
  return c.label != null && c.label.length;
}).length;

// I'm doing this so I can just guess a good max width on a column
// Switch trimmed for brevity
let maxWidth;
switch (visibleColumns) {
  case 1:
    maxWidth = 1000;
    break;
  case 2:
    maxWidth = 700;
    break;      
  default:
    maxWidth = 200;
    break;
  }

// Loop over my dynamic columns and find the longest value from the data
_.each(cols, c => {
  const comparer = Math.max(...this.data.map(d => String(d[c.field]).length));
});

// I then print the alpha equivalent to the length of the longest field into a hidden
// div and get the width and compare it with the max width based on columns

// i.e. if maxWidth is less than the length of the column then use that, else the div width

Пользовательский интерфейс элемента имеет свойства minWidth и width, но не максимальную ширину. И у них есть хорошая функция автоматической подсказки. Но попытка управлять таблицей оказалась труднее, чем она того стоит, поэтому я создам свой собственный компонент таблицы. Я обнаружил, что другие пошли по этому пути с таблицей Element UI и столкнулись с несколькими неприятностями.

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

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

https://jsfiddle.net/xtrvygfq/


person user1447679    schedule 13.08.2020    source источник
comment
Я не думаю, что вы можете использовать ‹table /›, но вы можете добиться этого с помощью flexbox. Думаю, мой вопрос к вам будет: нужно ли вам использовать элементы таблицы для размещения данных?   -  person David Liang    schedule 15.08.2020
comment
Полагаю, что нет, пока он выглядит как стол. Просто хитрый бизнес, пытаясь создать интеллектуальную таблицу, которая правильно усекает.   -  person user1447679    schedule 17.08.2020
comment
Хорошо, тогда это выполнимо. Вам придется использовать flexbox, чтобы они могли автоматически занимать лишнее пространство. Проблема заключалась бы в настройке ширины каждого столбца так, чтобы он выглядел как таблица. Поскольку вы просматриваете свои данные в цикле для получения информации, вы можете найти самое длинное значение в каждом столбце, вычислить процентное соотношение каждого и использовать его как ширину каждого столбца. У вас есть образцы тестовых данных, которые мы можем использовать? Я могу попробовать создать для вас демо.   -  person David Liang    schedule 17.08.2020
comment
@DavidLiang Я бы хотел привести пример, если у вас есть что-то на уме. Просто образцы данных в той скрипке, которую я опубликовал.   -  person user1447679    schedule 18.08.2020
comment
@DavidLiang вот скрипка. Я чувствую, что почти у цели. Но я хочу, чтобы столбцы занимали только необходимое пространство, а не распределялись равномерно, а последний столбец растягивал остаток, чтобы фактическая ширина таблицы составляла 100%. jsfiddle.net/xshcwqa4   -  person user1447679    schedule 18.08.2020
comment
Я тоже сделал демонстрацию: jsfiddle.net/davidliang2008/9tcj0dfp/169. Я не уверен, что вы этого хотите. Моя стратегия состоит в том, чтобы использовать среднюю длину строки для каждого столбца, вычислить ее процент и использовать это как ширину.   -  person David Liang    schedule 18.08.2020
comment
Круто @DavidLiang. Выглядит неплохо. Думаю, я могу использовать и то, и другое. Следующий шаг - (с учетом производительности) узнать, какие из них усечены, чтобы я мог показать всплывающую подсказку. Я видел несколько примеров, но меня немного беспокоят большие наборы данных. Может, мне стоит активировать логику при наведении курсора.   -  person user1447679    schedule 18.08.2020
comment
Раньше у меня были похожие проблемы. Я просто установил фиксированную длину на сервере, и все, что длиннее, будет обрезано.   -  person David Liang    schedule 18.08.2020
comment
Возникли проблемы с этим. Думаю, я хочу избегать функций, устанавливающих ширину. Можете ли вы взять мою последнюю скрипку и сделать эти ширины автоматически, а не растягивать @DavidLiang?   -  person user1447679    schedule 19.08.2020
comment
При использовании подхода flexbox вам нужно будет установить ширину, чтобы строки flexbox выглядели как строки таблицы.   -  person David Liang    schedule 19.08.2020


Ответы (1)


Css может решить вашу проблему.

.cell-overflow {
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-box-orient: vertical;
  display: -webkit-box;
  -webkit-line-clamp: 1;
}

Ваш HTML

<td v-for="h in colDefs">
    <div class="cell-overflow">{{d[h.field]}}</div>
</td>

https://jsfiddle.net/k2fh8b53/2/

person markcc    schedule 14.08.2020
comment
К сожалению, это не так просто. Я не хочу устанавливать фиксированную ширину, а макет таблицы должен быть автоматическим, чтобы он не распространялся по ширине таблицы. Пожалуйста, посмотрите мои (возможно, ужасные) примеры рассматриваемого макета стола. - person user1447679; 14.08.2020
comment
Я понимаю. Я неправильно понял вопрос - person markcc; 15.08.2020
comment
Я обновил свой ответ, поможет ли что-то подобное? - person markcc; 15.08.2020
comment
Я столкнулся с дополнительными сложностями при использовании таблицы в целом. Как вы думаете, можете ли вы взять этот пример и сделать его автоматической шириной для столбцов, но позволить последнему растягиваться, чтобы он выглядел на 100% ширины? Я не ожидал, что это будет так сложно. jsfiddle.net/xshcwqa4 - person user1447679; 19.08.2020
comment
Я не уверен, какой сценарий вы пытались придумать. Если вы знаете длину данных вашего контента, вы можете примерно установить длину ширины, как вы это делали в первом столбце. Однако, если ваши данные довольно случайны, предыдущий ответ, который я публикую, я думаю, является довольно общим и может соответствовать большей части данных. 1. jsfiddle.net/k2fh8b53/2 2. jsfiddle.net/zm1a3xr8/1 - person markcc; 20.08.2020