Showing Truncated Text Only on Hover with Vue

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



Leave a reply



Submit