Search code examples
javascriptcssreact-bootstraptruncatereact-table

How to truncate text in cell in Bootstrap Table in React?


I have a Bootstrap Table component, and one cell within that table is a URL. The URL can be long, so I'd like to automatically truncate it with an ellipsis to fit within the cell.

Here's an example of what the issue looks like.

You can see the URL and the Table exceed the width of the Card component they're in.

I managed to come up with a fix, but it's not ideal. Here's my code:

<div>
  <Accordion>
    {this.state.previous_entries.map(pe =>
      <Card key={pe.listing.id}>
        <CustomToggle eventKey={pe.listing.id}>{[formatAddress(pe), pe.listing.createdAt]}</CustomToggle>
        <Accordion.Collapse eventKey={pe.listing.id}>
          <Card.Body>
            <Table bordered style={{marginBottom: 0}}>
              <tbody>
                <tr>
                  <td className="bg-light">URL</td>
                  <td colSpan="3">
                    <!-- THIS PART -->
                    <a href={pe.listing.url}>
                      <span style={{textOverflow: "ellipsis", overflow: "hidden", whiteSpace:"nowrap", position: "fixed", maxWidth: "14%"}}>{ pe.listing.url }</span>
                    </a>
                  </td>
                </tr>
                <tr>
                  <td className="bg-light">Monthly Rent</td>
                  <td>{ pe.listing.monthly_rent ? pe.listing.monthly_rent + "万円" : "N/A" }</td>
                  <td className="bg-light">礼金</td>
                  <td>{ pe.listing.reikin !== null ? (pe.listing.reikin !== 0 ? pe.listing.reikin + "ヶ月" : pe.listing.reikin) : "N/A" }</td>
                </tr>
                <tr>
                  <td className="bg-light">敷金</td>
                  <td>{ pe.listing.security_deposit !== null ? (pe.listing.security_deposit !== 0 ? pe.listing.security_deposit + "ヶ月" : pe.listing.security_deposit) : "N/A" }</td>
                  <td className="bg-light">面積</td>
                  <td>{ pe.listing.square_m ? pe.listing.square_m + "m²" : "N/A" }</td>
                </tr>
                <tr>
                  <td className="bg-light">Closest Station</td>
                  <td>{ pe.listing.closest_station ? pe.listing.closest_station : "N/A" }</td>
                  <td className="bg-light">Walking Time</td>
                  <td>{ pe.listing.walking_time ? pe.listing.walking_time + "分" : "N/A" }</td>
                </tr>
                <tr>
                  <td className="bg-light">Availability</td>
                  <td>{ pe.listing.availability ? pe.listing.availability : "N/A" }</td>
                  <td className="bg-light">Interest</td>
                  <td>{ pe.property.interest ? pe.property.interest : "N/A" }</td>
                </tr>
              </tbody>
            </Table>
          </Card.Body>
        </Accordion.Collapse>
      </Card>
    )}
  </Accordion>
</div>

My 'fix' was adding the maxWidth: "14%" style to the span containing the URL. But this doesn't work great in all cases, depending on the size of the window. Which makes sense because it's a static value.

Here's what my 'fix' looks like.

Does someone know a better way of automatically truncating the URL so that the Table doesn't exceed the Card?


Solution

  • This approach is more flexible when it comes to various screen sizes, as you are not specifying a width for the text-overflow.

    table {
      table-layout: fixed;
      width: 100%;
    }
    
    td>a {
      display: block;
      text-overflow: ellipsis;
      overflow: hidden;
      max-width: 100%;
    }
    
    td>a>span {
      white-space: nowrap;
    }
    <div>
      <Accordion>
        {this.state.previous_entries.map(pe =>
        <Card key={pe.listing.id}>
          <CustomToggle eventKey={pe.listing.id}>{[formatAddress(pe), pe.listing.createdAt]}</CustomToggle>
          <Accordion.Collapse eventKey={pe.listing.id}>
            <Card.Body>
              <Table bordered style={{marginBottom: 0}}>
                <tbody>
                  <tr>
                    <td className="bg-light">URL</td>
                    <td colSpan="3">
                      <!-- THIS PART -->
                      <a href={pe.listing.url}>
                        <span style={{textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap", position: "fixed", maxWidth: "14%"}}>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</span>
                      </a>
                    </td>
                  </tr>
                  <tr>
                    <td className="bg-light">Monthly Rent</td>
                    <td>{ pe.listing.monthly_rent ? pe.listing.monthly_rent + "万円" : "N/A" }</td>
                    <td className="bg-light">礼金</td>
                    <td>{ pe.listing.reikin !== null ? (pe.listing.reikin !== 0 ? pe.listing.reikin + "ヶ月" : pe.listing.reikin) : "N/A" }</td>
                  </tr>
                  <tr>
                    <td className="bg-light">敷金</td>
                    <td>{ pe.listing.security_deposit !== null ? (pe.listing.security_deposit !== 0 ? pe.listing.security_deposit + "ヶ月" : pe.listing.security_deposit) : "N/A" }</td>
                    <td className="bg-light">面積</td>
                    <td>{ pe.listing.square_m ? pe.listing.square_m + "m²" : "N/A" }</td>
                  </tr>
                  <tr>
                    <td className="bg-light">Closest Station</td>
                    <td>{ pe.listing.closest_station ? pe.listing.closest_station : "N/A" }</td>
                    <td className="bg-light">Walking Time</td>
                    <td>{ pe.listing.walking_time ? pe.listing.walking_time + "分" : "N/A" }</td>
                  </tr>
                  <tr>
                    <td className="bg-light">Availability</td>
                    <td>{ pe.listing.availability ? pe.listing.availability : "N/A" }</td>
                    <td className="bg-light">Interest</td>
                    <td>{ pe.property.interest ? pe.property.interest : "N/A" }</td>
                  </tr>
                </tbody>
              </Table>
            </Card.Body>
          </Accordion.Collapse>
        </Card>
        )}
      </Accordion>
    </div>