Showing truncated text only on hover with Vue
The problem is that you have only one property to control the truncation of all items.
Firstly, you need to ensure that each club has its own boolean to control the text truncation. Lets use your already existing computed property to add a new reactive property for each club:
formattedClubs () {
return this.clubs.reduce((c, n, i) => {
if (i % 4 === 0) c.push([]);
c[c.length - 1].push(n);
this.$set(n, 'truncate', true); // Here we add the new reactive property.
return c;
}, []);
}
Secondly, let's use the <template>
to handle visual things, keeping the right separation of concerns, using the new individual club.truncate
property with a v-if
/v-else
block:
<h4 class="card-title"
@mouseenter="club.truncate = false"
@mouseleave="club.truncate = true">
<template v-if="club.truncate">{{trucateText(club.description)}}</template>
<template v-else>{{club.description}}</template>
</h4>
And now, the trucateText
method only needs to care about returning the truncated text, since it's only called if we're truncating a description of one club:
methods: {
trucateText (value) {
const length = 30;
return value.length <= length ?
value : value.substring(0, length) + "...";
}
}
Take a look at the fully working code here if any doubts persists.
How can I showing truncated text only on hover without change height of box list?
We can see that you're using bootstrap-vue. Nice, so you can use v-b-tooltip directive and let itself control the hover behavior. As you don't need to track it by yourself anymore for each club, you can remove that reative property from your computed property formattedClubs
:
this.$set(n, 'truncate', true); // Remove this line.
Now, update your template to use the directive only if the truncation is needed:
<h4 class="card-title"
v-if="club.description.length > 30"
v-b-tooltip.hover.bottom
:title="club.description">
{{trucate(club.description)}}
</h4>
<h4 v-else>{{club.description}}</h4>
And, of course, you can now style it the way you want overriding the right Boostrap styles:
.tooltip.show {
opacity: 1;
}
.tooltip-inner {
background: #fff;
color: #000;
padding: .5em 1em;
border: 1px solid #bbb;
box-shadow: 0 3px 8px rgba(0, 0, 0, .15);
}
.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow, .tooltip.bs-tooltip-bottom .arrow {
position: relative;
background: #fff;
top: 1px;
width: 16px;
}
.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before, .tooltip.bs-tooltip-bottom .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::after, .tooltip.bs-tooltip-bottom .arrow::after {
bottom: 0;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::after, .tooltip.bs-tooltip-bottom .arrow::after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #fff;
border-width: 8px;
margin-left: -8px;
}
.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before, .tooltip.bs-tooltip-bottom .arrow::before {
border-color: rgba(187, 187, 187, 0);
border-bottom-color: #bbb;
border-width: 9px;
margin-left: -9px;
}
Take a look at the fully working sampe here if you want.
Looking for a way to show tooltip only when the element is truncated
You can create a method to check your text length, and display tooltip only when text length is bigger than a particular threshold (hence it was truncated). For example:
<q-td v-for="(col,index) in props.cols" :key="col.name">
<span class="truncate">{{ col.value }}</span>
<q-tooltip content-class="bg-primary" v-if="isTooltip(col.value)">
{{ col.value }}
</q-tooltip>
</q-td>
methods: {
isTooltip(col) {
return col.length > 10
}
}
vue.js components : How to truncate the text in the slot element in a component?
The same thing on similar way can be:
in your main.js file:
var filter = function(text, length, clamp){
clamp = clamp || '...';
var node = document.createElement('div');
node.innerHTML = text;
var content = node.textContent;
return content.length > length ? content.slice(0, length) + clamp : content;
};
Vue.filter('truncate', filter);
in your template:
{{data.content | truncate(300, '...')}}
show Tooltip only when the ellipsis is active
Overflow of an element can be detected in JavaScript with this helper, using Angular ElementRef
and a formula from this answer:
function isTextTruncated(element: ElementRef): boolean {
const e = element.nativeElement;
return e.scrollWidth > e.clientWidth;
}
Then, in your component, use it referencing the element with a "@ViewChild
" property:
@ViewChild('hospitalName') hospitalNameElement: ElementRef;
isHospitalNameTruncated(): boolean {
return isTextTruncated(this.hospitalNameElement);
}
Finally, in the template, add the identifier #hospitalName
and call isHospitalNameTruncated()
to customize the tooltip text:
<td mat-cell [attr.id]="hospital.organizational_id + '_hospitalname'"
*matCellDef="let hospital">
<div id="hospital_name" #hospitalName class="truncate"
[matTooltip]="isHospitalNameTruncated() ? hospital.organization_name : null ">
{{hospital.organization_name}}
</div>
</td>
How to truncate in Nuxt (Vue.js)
Your code is fine. It just appears the string isn't defined immediately. You can add a guard like:
(string || '').substring(0, value) + '…'
Though, it might be better to not render that part of your code until things are ready. You can do something like this (assuming you're working with an object)
<div v-if="post">
{{ post.excerpt | truncate(3) }}
</div>
<div v-else>
Post is loading...
</div>
Related Topics
How to Serve Fonts from Different Servers for Ie Users
Two Columns with Variable Width and a Fixed Gap Between Them
Margin Goes Outside Div When Border Is Removed
Flex-Box Box-Sizing: Border-Box Not Working
Transform-Origin Not Working on Firefox
Creating Gradient Lines in CSS
Bad Cursor in Select/Option, Ie
How to Style: Root Without !Important Using Proper Specificity
Mix-Blend-Mode Doesn't Work on Chrome
Weird Float Rendering in Chrome When Using Media Queries
Unwanted Bolding Added to Font in Browsers
Accessing The CSS in Browser Using Question Mark () in End
Preventing a <Pre> from Wrapping Inside of a Table
How to Test @Media Print with Protractor or Selenium
Custom Classname Semantic UI React