1

I have a table and some cells overflow. These <td>'s have a class that give them an ellipsis at the end. But is there a way I can add a small button/span/whatever AFTER the ellipsis?

<td #elCol ...>
  <ng-container *ngIf="overflows(elCol)">
    YES <!-- this is displayed when it overflows, the function works -->
  </ng-container>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
  <button *ngIf="overflows(elCol)">
    click me <!-- Can't get this to displayed because it is behind the text -->
  </button>            
</td>

td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 20rem;
}

Both HTML/SCSS and TS/JS solutions could be employed

1 Answer 1

2

you may have a .container element inside the <td>, wrapping the elements you need next to each other thus styling it with display: flex.

Then the total width of the <td> will be driven by its style as you did with width: 20rem and yet the text intended to be truncated will have its width decided by that amount minus the space occupied by the button following.

function overflows(el) {
   return el.scrollWidth > el.clientWidth;
}

document.addEventListener('DOMContentLoaded', () => {
  const text1 = document.querySelector('tr:nth-child(1) .truncate');
  const text2 = document.querySelector('tr:nth-child(2) .truncate');
  console.log(`The text on the first row does overflow: ${overflows(text1)}`);
  console.log(`The text on the second row does overflow: ${overflows(text2)}`);
})
td {
  border: solid 1px;    
  padding: .5em;    
  max-width: 20rem;
}

.container{
  display: flex;
  flex-wrap: nowrap;
}

.truncate{  
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.action{
  /*to force the button having a width large enough to avoid word wrap*/
  min-width: fit-content;
}
<table>
  <tr>
    <td>      
      <div class="container">
        <div class="truncate">              
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.        
        </div>        
        <button class="action">click me</button>                  
      </div>            
    </td>
  </tr> 
  
  <tr>
    <td>      
      <div class="container">
        <div class="truncate">Short text</div>        
        <button class="action">click me</button>                  
      </div>            
    </td>
  </tr> 
</table>

The demo is using vanilla js/css and not reproducing strictly your original intention aimed at Angular. By the way I understand what the logic *ngIf="overflows(elCol)" does is rendering the element if the content overflows the .truncate element size. So to show the concept I also implemented my own version of the overflows function that will return true or false given the element you are willing to check.

In the demo such function is invoked over both the .truncate elements existing on the 2 table rows where the first one is overflowing and the second is not.

Sign up to request clarification or add additional context in comments.

4 Comments

It's not a good idea to make a td display:flex. Fine if there's only one cell in the row, but it will break the table structure if there are multiple cells in the row.
@Alohci yes I agree so I edited the answer adding a container styled as display: flex ..thanks for pointing out
this unfortunately breaks my overflows function which was just return el.scrollWidth > el.offsetWidth;. Do you maybe have a suggestion on how I could now detect if a text oveflows in the cell? If I did not need to put that check, your proposal works great btw!
you should use el.scrollWidth > el.clientWidth; to check if a given el has content overflowing its size. I implemented that function also and I show on console how it behaves on 2 different cases

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.