Comments 8
Лисинер, тулитип, опрции…
Проверьте текст на ошибки/опечатки
Проверьте текст на ошибки/опечатки
0
Не пробовали использовать material CDK?
+1
Здравствуйте. Спасибо за статью.
Как мне кажется — вы подошли к решению задачи не с той стороны. Внутри функции «buildTooltip» вы вычисляете размеры будущего окошка на основе размеров строки и количества переданных «list». И всё ради того что бы проставить элементу нужные размеры и позицию. Почти всё это можно сделать средствами только лишь css. Например вот набросок html+css
Ни написав ни строчки кода на js мы получили заветный тултип. Вот его отличия от вашей реализации в плане функциональности:
1. Он всегда справа
2. Его ширина не зависит от оставшейся справа длины строки
3. Высота emploee не зависит от высоты строки
4. Его разметка всегда на странице, просто скрыта за display: none.
5. Не реализован показ по клику
6. Окно находится рядом с иконкой, а не в конце body
Если же что-то из этих отличий критично — то всё-таки пишем js код:
1. Не нужно думать за браузера. Намного проще положить элемент на страницу и взять его width\height, чем считать эти свойства самому. Соответственно что бы решить проблему 1 — на событие mouseover берём ширину этого элемента и смотрим — не выходит ли он за границу дозволенного(в вашем случае вы считаете width\height сами — и это самый сложный участок кода). Если выходит — меняем css свойство «left: 100%» на «right: 100%».
2. Тоже самое — с помощью width\height элемента просто превращаем max-width в width на mouseover
3. Тоже 1 строчка в mouseover на height для .emploee
4. Эта проблема решается просто — создаём динамически тултип(как это сделано у вас в showTooltip), только бахаем его не в конец body, а сразу за элементом: this.viewContainerRef.createComponent(TooltipComponent).
5. Просто добавить класс для отмены :hover и добавлять\убирать ещё один при клике для показа
6. Здесь уже посложнее, но подход тот же. Сначала добавляем элемент в конец body -> берём его width\height -> проставляем left\top
Как правило когда я выполняю подобного рода задачки первое что нужно узнать — а нужно ли вообще писать код? Вполне возможно что эти ограничения вполне устроят заказчика — например если справа всегда будет 320px, ширина не доходит до правого края(и это ок), высота строки всегда одинаковая, ну и так далее. По моему опыту часто удаётся упростить код в разы путём незначительных модификаций в требования к функционалу.
Ещё бросается в глаза пара моментов по коду:
1. Если вы используете any в typescript — то скорее всего вы что то делаете не так. Во всех any в вашем коде тип переменной вполне определён.
2. В этом месте:
3. Если вам при использовании angular приходится работать напрямую с элементами на странице — скорее всего вы что-то делаете не так. Вместо поиска родителя по классу — можно просто заинжектить родительский компонент и уже у него брать необходимые свойства. Вместо этого:
Вместо прямого изменения списка классов есть ngClass, и так далее
4. В функции buildTooltip вы получаете переменную «matRow» но ниже её не используете — странно :)
Надеюсь идею уловили :)
Как мне кажется — вы подошли к решению задачи не с той стороны. Внутри функции «buildTooltip» вы вычисляете размеры будущего окошка на основе размеров строки и количества переданных «list». И всё ради того что бы проставить элементу нужные размеры и позицию. Почти всё это можно сделать средствами только лишь css. Например вот набросок html+css
<div class="ceil">
<div class="icon"></div>
<div class="tooltip">
<div class="emploee"></div>
<div class="emploee"></div>
<div class="emploee"></div>
</div>
</div>
<style>
.ceil {
position: relative;
}
.icon:hover + .tooltip {
display: flex;
}
.tooltip {
display: none;
position: absolute;
flex-wrap: wrap;
bottom: 0;
left: 100%;
max-width: 320px;
}
.emploee {
width: 160px;
}
</style>
Ни написав ни строчки кода на js мы получили заветный тултип. Вот его отличия от вашей реализации в плане функциональности:
1. Он всегда справа
2. Его ширина не зависит от оставшейся справа длины строки
3. Высота emploee не зависит от высоты строки
4. Его разметка всегда на странице, просто скрыта за display: none.
5. Не реализован показ по клику
6. Окно находится рядом с иконкой, а не в конце body
Если же что-то из этих отличий критично — то всё-таки пишем js код:
1. Не нужно думать за браузер
2. Тоже самое — с помощью width\height элемента просто превращаем max-width в width на mouseover
3. Тоже 1 строчка в mouseover на height для .emploee
4. Эта проблема решается просто — создаём динамически тултип(как это сделано у вас в showTooltip), только бахаем его не в конец body, а сразу за элементом: this.viewContainerRef.createComponent(TooltipComponent).
5. Просто добавить класс для отмены :hover и добавлять\убирать ещё один при клике для показа
6. Здесь уже посложнее, но подход тот же. Сначала добавляем элемент в конец body -> берём его width\height -> проставляем left\top
Как правило когда я выполняю подобного рода задачки первое что нужно узнать — а нужно ли вообще писать код? Вполне возможно что эти ограничения вполне устроят заказчика — например если справа всегда будет 320px, ширина не доходит до правого края(и это ок), высота строки всегда одинаковая, ну и так далее. По моему опыту часто удаётся упростить код в разы путём незначительных модификаций в требования к функционалу.
Ещё бросается в глаза пара моментов по коду:
1. Если вы используете any в typescript — то скорее всего вы что то делаете не так. Во всех any в вашем коде тип переменной вполне определён.
2. В этом месте:
@Input() showOnClick: boolean = false;
не обязательно указывать boolean. Если вы устанавливаете false\true при создании — typescript сам поймёт какой это тип(просто лишний код)3. Если вам при использовании angular приходится работать напрямую с элементами на странице — скорее всего вы что-то делаете не так. Вместо поиска родителя по классу — можно просто заинжектить родительский компонент и уже у него брать необходимые свойства. Вместо этого:
this._document.querySelector('body').appendChild(this.contentCmpRef.location.nativeElement);
В angular тоже есть более высокоуровневая абстракция — viewContainerRef.createComponent. Вместо прямого изменения списка классов есть ngClass, и так далее
4. В функции buildTooltip вы получаете переменную «matRow» но ниже её не используете — странно :)
Надеюсь идею уловили :)
+1
Да, исправила ошибки/ опечатки.
Нужен был тултип именно такого вида, а в Материал этого нет.
Длина тултипа должна быть плавающей, это обязательное условие, потому что похожих таблиц не одна а много, и расстояние до конца экрана всегда величина переменная.
Его надо показать чуть сбоку от элемента, чтобы было видно количество человек.
По ней проходит проверка, а нужные данные записываются в переменную родителя сразу.
По поводу скрытия тултипа идея хорошая, я подумаю над ее реализацией! Спасибо за советы!
Нужен был тултип именно такого вида, а в Материал этого нет.
Длина тултипа должна быть плавающей, это обязательное условие, потому что похожих таблиц не одна а много, и расстояние до конца экрана всегда величина переменная.
Его надо показать чуть сбоку от элемента, чтобы было видно количество человек.
В функции buildTooltip вы получаете переменную «matRow» но ниже её не используете — странно :)
По ней проходит проверка, а нужные данные записываются в переменную родителя сразу.
По поводу скрытия тултипа идея хорошая, я подумаю над ее реализацией! Спасибо за советы!
0
Почему тултип не построен поверх angular/cdk?
0
Для начала неплохо бы исправить слово «коммандировка» в самом приложении, а то глаза режет…
0
Sign up to leave a comment.
Создание динамического tooltip в Angular2+ приложениях