У меня есть компонент, предоставленный внешней библиотекой Angular, которая является частным проектом с открытым исходным кодом для компании, в которой я работаю. Компонент имеет свое содержимое, внедренное в него из Observable, и эти данные недоступны при первоначальной визуализации. Рассматриваемый компонент - это ячейка таблицы данных, часть большой таблицы данных, очень похожая на таблицу данных Material .
Одна из этих ячеек имеет длинную строку, которая, в зависимости от данных, возвращаемых из API, может переполниться из контейнера. В этом случае мне нужно укоротить строку, выделив середину и заменив ее на «...». Строка представляет собой путь к файлу, например, «C: \ Действительно \ действительно \ действительно \ действительно \ действительно \ длинный \ путь \ к \ file.txt». Скажем, переполнение было скрыто в разделе '\ path \ to \ file.txt', я бы хотел, чтобы середина была вырезана примерно так: 'C: \ Действительно \ действительно ... \ long \ path \ to \ file.txt' , Это похоже на то, как macOS обрабатывает длинные пути к файлам в Finder. Я могу сделать это нормально, используя трубу, однако я не уверен, как получить ширину компонента. Я пытался использовать ViewChild, как это:
@ViewChild('path') public path: ElementRef;
Однако, когда я смотрю на свойства измерения в path.nativeElement
объекте, все они равны 0 - например:
scrollHeight: 0
scrollLeft: 0
scrollTop: 0
scrollWidth: 0
Я думаю, это потому, что данные загружаются в таблицу после загрузки. Я попытался просмотреть переменную path
в ngAfterViewInit
, и она получает правильный компонент, но атрибуты innerHTML, text, content все пусты. Как бы получить самую последнюю версию этой переменной?
В качестве альтернативы, если у вас есть какие-либо другие предложения о том, как мне этого добиться, это было бы замечательно. Спасибо.
РЕДАКТИРОВАТЬ: Некоторые обновления. Теперь у меня есть два варианта: я могу использовать Pipe в HTML и отправить путь ElementRef в pipe, например:
<div #path>{{ value | truncate: path }}</div>
И код трубы выглядит так:
@Pipe({ name: 'truncate' })
export class TruncatePipe implements PipeTransform {
public transform(value: string, element: any): string {
const { scrollWidth, clientWidth } = element;
// computation to figure out what the value of the new string should be
return value;
}
}
Элемент имеет необрезанное значение, но scrollWidth и clientWidth равны, что неверно, если значение слишком длинное для контейнера (поэтому оно переполняется); scrollWidth должен быть длиннее clientWidth. Это означает, что я не могу вычислить, сколько символов должно быть усечено, так как канал не знает, как далеко он переполняется. Я думаю, что причина того, что эти две переменные имеют одно и то же значение, заключается в том, что данные еще не были внедрены, поэтому элемент (div, то есть элемент block) принимает ширину своего контейнера. Если я проверяю элемент после, я вижу, что scrollWidth больше, чем clientWidth.
Другой способ, которым я пытался, - это использовать прокси-функцию в моем классе компонентов, которая затем возвращает значение из канала, например:
public truncatePath(value: string, element: any) {
return new TruncatePipe().transform(value, element);
}
и HTML:
<div #path>{{ truncatePath(value, path) }}</div>
Это работает (clientWidth и scrollWidth различаются), но многократно запускает функцию, что, очевидно, снижает производительность приложения.
РЕДАКТИРОВАТЬ 2: если я добавлю код канала в setTimeout
, clientWidth будет правильным значением, и строка будет усечена, однако, поскольку она находится в setTimeout, она не отображает эту строку.