Last updated Jan 20, 2020

Card Components

What if rendering a Trello card was as simple as adding a paragraph <p> or a link <a>? With the card component, its as simple as <trello-card>!

Although we have the awesome card embed that lets you embed a Trello card into your project, it relies on a Trello user being logged in and isn't as flexible as some developers want it to be. If you are looking for a way to render native Trello cards in your project in a more flexible and controllable way, this card component is for you.

Live Example

Below is a live example of the card component:

And the code for the above ☝️is below πŸ‘‡ – copy and paste it into an html file and give it a try!

1
2
<script>
  const container = document.getElementById("card-component-example");
  container.innerText = "Loading...";

  const scriptSrc = window.customElements
    ? "/card.min.js"
    : "/card-polyfilled.min.js";
  const cardJs = document.createElement("script");
  cardJs.crossOrigin = "anonymous";
  cardJs.src = "https://p.trellocdn.com" + scriptSrc;

  cardJs.onload = function () {
    fetch(
      "https://api.trello.com/1/card/MA6fxIg3?fields=name,closed,url,badges,idAttachmentCover,labels&attachments=cover&customFields=true&customFieldItems=true&members=true&stickers=true"
    )
      .then(function (resp) {
        return resp.json();
      })
      .then(function (card) {
        const cardEl = document.createElement("trello-card");
        cardEl.card = card;
        container.innerHTML = "";
        container.appendChild(cardEl);
      });
  };
  document.head.appendChild(cardJs);
</script>

<div style="width:272px;background-color:#dfe1e6;padding:8px;">
  <div id="card-component-example">
    <!-- Card Component Will Be Inserted Here -->
  </div>
</div>

Loading the Card Component Script

The main component script you should include can be found here:

https://trellocdn.com/card.min.js

However, if you want to support Edge, we recommend loading the polyfill that we have hosted at https://trellocdn.com/card-polyfilled.min.js. Below is an example of how to load the polyfill to support Edge:

1
2
<!DOCTYPE html>
<html>
  <head>
    <!-- Your head content -->
    <script>
      const scriptSrc = window.customElements
        ? "/card.min.js"
        : "/card-polyfilled.min.js";
      window.cardComponentLoaded = new Promise(function (resolve) {
        const cardJs = document.createElement("script");
        cardJs.crossOrigin = "anonymous";
        cardJs.src = "https://p.trellocdn.com" + scriptSrc;
        cardJs.onload = resolve;
        document.head.appendChild(cardJs);
      });
    </script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

This unusual script loading fork is a result of the Microsoft Edge browser not currently having built-in support for custom elements. We don't want to punish the other browsers which do have support so we only load the full polyfilled bundle when we detect that the browser needs it.

If your browser support matrix is limited to browsers that have native support for custom elements (see: https://caniuse.com/#feat=custom-elementsv1) you could simplify this to a single script tag:

1
2
<!-- If you don't support browsers like Edge -->
<script
  src="https://p.trellocdn.com/card.min.js"
  crossorigin="anonymous"
></script>

As with all of the scripts Trello hosts, when we announce updates on the changelog we will push changes to the staging versions of the component scripts first:

Rendering Cards in Native Javascript

You can render a card by passing in an object that contains the card's field data to an element returned from the component. The only required field for a card is a name. For example, here is the minimal code required to render a card:

1
2
const cardEl = document.createElement("trello-card");

cardEl.card = {
  name: "Name of card", // required
  url: "https://trello.com/c/something", // required
};

document.body.appendChild(cardEl);

But that isn't very exciting! We support all of the fields from a card required to render a full-fledged card front. Below is an example making use of all of the supported fields:

1
2
const cardEl = document.createElement("trello-card");

// Determines whether colorblind labels should be used or not. Default is true.
cardEl.colorblind = false;

// Determines whether to show text on labels. Default is true.
cardEl.labeltext = true;

cardEl.card = {
  id: "5b907e0e39cccd595f1c8bfa",
  name: "Name of card", // Required
  url: "https://trello.com/c/something", // Required
  closed: false,
  idAttachmentCover: null,
  badges: {
    attachmentsByType: {
      trello: { board: 1, card: 0 },
    },
    location: false,
    votes: 0,
    viewingMemberVoted: false,
    subscribed: true,
    checkItems: 5,
    checkItemsChecked: 4,
    comments: 3,
    attachments: 7,
    description: true,
    due: null,
    dueComplete: false,
  },
  labels: [
    {
      id: "5b8fd55d451e437262fe7aff",
      idBoard: "599dbf8d693c9eeaed69ca09",
      name: "bug",
      color: "red",
    },
  ],
  stickers: [],
  attachments: [], // Only need attachment for idAttachmentCover
  members: [
    {
      id: "556c8537a1928ba745504dd8",
      avatarHash: "0b48c7057767cca8f339109b27a064d7",
      fullName: "Matt Cowan",
      username: "mattcowan",
      initials: "MC",
    },
  ],
  customFields: [],
  customFieldItems: [],
};

// There is a custom event that is fired when a user clicks on the labels that
// you can listen and respond to.
cardEl.addEventListener("labelTextChanged", (e) => {
  console.log("labeltext property is now", e.detail.labeltext);
});

document.body.appendChild(cardEl);

Rendering Cards in React

React 16.x still has some quirks when it comes to handling native custom elements so we recommend you follow our example below; in this example, we fetch a card from the Trello REST API, take the data returned, and turn it into a custom card rendered as a React component:

1
2
import React from "react";

// ...

const API_ROOT = "https://api.trello.com/1/card/";
const CARD_QUERY = `?fields=name,closed,url,badges,idAttachmentCover,labels&attachments=cover&customFields=true&customFieldItems=true&members=true&stickers=true&key=${API_KEY}&token=${API_TOKEN}`;

let card;
fetch(`${API_ROOT}${idCard}${CARD_QUERY}`) // Fetch card data from Trello API
  .then((resp) => resp.json())
  .then((cardData) => (card = cardData));

// ...

class TrelloCardWrapper extends React.Component {
  constructor(props) {
    super(props);

    this.setRef = this.setRef.bind(this);
    this.onClick = this.onClick.bind(this);
    this.onLabelTextChanged = this.onLabelTextChanged.bind(this);
  }

  componentDidMount() {
    if (!this.el) {
      return;
    }
    this.el.card = this.props.card;
    this.el.addEventListener("click", this.onClick);
    this.el.addEventListener("labelTextChanged", this.onLabelTextChanged);
  }

  componentDidUpdate() {
    if (!this.el) {
      return;
    }
    this.el.card = this.props.card;
  }

  onClick(e) {
    if (typeof this.props.onClick === "function") {
      e.preventDefault();
      this.props.onClick();
    }
  }

  onLabelTextChanged(e) {
    if (typeof this.props.onLabelTextChanged === "function") {
      this.props.onLabelTextChanged(e.detail.labeltext);
    }
  }

  setRef(el) {
    this.el = el;
  }

  render() {
    return (
      <trello-card
        ref={this.setRef}
        colorblind={this.props.colorblind}
        labeltext={this.props.labelText}
      />
    );
  }
}

// ...

Additional Framework Support

In general, framework support for custom elements is quite good. That said, there may be some quirks to how to use a custom element in your framework of choice. We suggest taking a look at https://custom-elements-everywhere.com/ to see if there is anything special you would need to do in your framework to use the Trello card component.

Properties

The component is made such that it works if you pass it a full response from t.card('all') or, as the example above demonstrates, a JSON response from the 1/cards/{idCard} endpoint from Trello's REST API.

The following properties are specific to the component and can be explicitly set to control the display of the card:

NameValueDetails
colorblindBoolean
Default: false
Determines whether to render the labels with colorblind-friendly patterns.
labeltextBoolean
Default: true
Determines whether to render the name field for labels.

Events

There is a custom event, labelTextChanged , that fires when the visibility of label text is toggled by clicking on a label on the card. event.detail.labeltext will have the new value of the labeltext property.

In addition to any custom events above, normal DOM events can be used as well. For example, if you wanted to add your own handler for a click on the card, and not have it open a new tab with the card URL you would use:

1
2
cardElement.addEventListener("click", (e) => {
  e.preventDefault();

  // ...
});

Rate this page: