Collection Component
This component is used to render a collection of items. It can be used to render a filters & pagination component for a list of items.
Imports
import EccUtilsDesignCollection from '@elixir-cloud/design/dist/react/collection/index';
import EccUtilsDesignCollectionType from '@elixir-cloud/design/dist/components/collection/collection';Example
EccUtilsDesignCollection
  import { useEffect, useState } from 'react';
  import EccUtilsDesignCollectionType from '@elixir-cloud/design/dist/components/collection/collection';
  import EccUtilsDesignCollection from '@elixir-cloud/design/dist/react/collection/index';
 
  export default function collection() {
    const [items, setItems] = useState([]);
    const [search, setSearch] = useState('');
    const [tag, setTag] = useState('');
 
    const fetchDummyData = async (page, limit, searchString, tags) => {
      const res = await fetch(
        `https://jsonplaceholder.typicode.com/todos?_page=${page}&_limit=${limit}${
          searchString ? `&title_like=${searchString}` : ''
        }${tags ? `&completed=${tags === 'SUCCESS'}` : ''}`,
      );
      const data = await res.json();
      return data.map((item, index) => ({
        index: index + 1,
        name: item.title,
        key: `item-${item.id}`,
        lazy: true,
        tag: {
          name: item.completed ? 'SUCCESS' : 'ERROR',
          type: item.completed ? 'success' : 'danger',
        },
      }));
    };
 
    useEffect(() => {
      const fetchData = async () => {
        const dataInitial = await fetchDummyData(1, 5, '', '');
        setItems(dataInitial);
      };
 
      fetchData();
    }, []);
 
    const handleExpand = async (e) => {
      // Check if child already exists
      const children = e.target.querySelectorAll(`[slot="${e.detail.key}"]`);
      if (children.length === 0) {
        // Add child to ecc-utils-design-collection
        const res = await fetch(
          `https://jsonplaceholder.typicode.com/todos/${e.detail.key.split('-')[1]}`,
        );
        const data = await res.json();
        const child = document.createElement('div');
        child.setAttribute('slot', e.detail.key);
        child.innerHTML = `<p>Title: ${data.title}</p>`;
        e.target.appendChild(child);
      }
    };
 
    const handleFilter = async (e) => {
      if (e.detail.key === 'title') {
        setSearch(e.detail.value);
        const data = await fetchDummyData(1, 5, e.detail.value.toLowerCase(), tag);
        const newItems = data.map((item, index) => ({
          index: index + 1,
          name: item.title,
          key: `item-${item.id}`,
          lazy: true,
          tag: {
            name: item.completed ? 'SUCCESS' : 'ERROR',
            type: item.completed ? 'success' : 'danger',
          },
        }));
        e.target.items = newItems;
        if (data.length < 5) {
          e.target.totalItems = data.length;
        }
      } else if (e.detail.key === 'tag') {
        setTag(e.detail.value);
        const data = await fetchDummyData(1, 5, search, e.detail.value);
        const newItems = data.map((item, index) => ({
          index: index + 1,
          name: item.title,
          key: `item-${item.id}`,
          lazy: true,
          tag: {
            name: item.completed ? 'SUCCESS' : 'ERROR',
            type: item.completed ? 'success' : 'danger',
          },
        }));
        e.target.items = newItems;
        if (data.length < 5) {
          e.target.totalItems = data.length;
        }
      }
    };
 
    const handlePageChange = async (e) => {
      if (e.detail.page === 3) {
        setTimeout(() => {
          document
            .querySelector<EccUtilsDesignCollectionType>('ecc-utils-design-collection')
            .error('This is an error message of page 3!');
        }, 1000);
        return;
      }
      const data = await fetchDummyData(e.detail.page, 5, search, tag);
      for (let i = 0; i < data.length; i += 1) {
        const element = data[i];
        const existingItem = e.target.items.find((item) => item.key === `item-${element.id}`);
        if (existingItem) {
          e.target.items = e.target.items.filter((item) => item.key !== `item-${element.id}`);
        }
        e.target.items = [
          ...e.target.items,
          {
            index: (e.detail.page - 1) * 5 + i + 1,
            name: element.title,
            key: `item-${element.id}`,
            lazy: true,
            tag: {
              name: element.completed ? 'SUCCESS' : 'ERROR',
              type: element.completed ? 'success' : 'danger',
            },
          },
        ];
      }
      setItems(e.target.items);
      if (data.length < 5) {
        e.target.totalItems = (e.detail.page - 1) * 5 + data.length;
      }
    };
 
    return (
      <EccUtilsDesignCollection
        items={items}
        filters={
          [
            {
              key: 'title',
              type: 'search',
              placeholder: 'Search',
            },
            {
              key: 'tag',
              type: 'select',
              options: ['SUCCESS', 'WARNING', 'ERROR', 'DEFAULT', 'PRIMARY'],
              placeholder: 'Filter by tag',
              selectConfig: {
                // multiple: true,
              },
            },
          ]
        }
        onEccUtilsExpand={(e) => handleExpand(e)}
        onEccUtilsFilter={(e) => handleFilter(e)}
        onEccUtilsPageChange={handlePageChange}
      >
        <div slot='item-5'>Child item-5 without lazy loading</div>
      </EccUtilsDesignCollection>
    );
  }Properties
| Property | Required | Default | Type | Description | 
|---|---|---|---|---|
items | true | Array | An array of items to render | |
filters | false | Array | An array of filters to render | |
totalItems | false | Number | The total number of items in the collection. If not provided, the collection will render pagination without fixed page numbers. | |
pageSize | false | 5 | Number | The number of items per pagination. | 
items*
| Property | Required | Default | Type | Description | 
|---|---|---|---|---|
key | true | String | The key of the item | |
index | true | Number | The index of the item | |
name | true | String | The name of the item | |
lazy | false | false | Boolean | Whether or not the contents of the item should be lazy loaded | 
tag | false | Object | The tag to render with the item | 
filters
| Property | Required | Default | Type | Description | 
|---|---|---|---|---|
key | true | String | The key of the filter | |
type | true | search | select | The type of the filter. | |
options | false | Array | The options to render for the filter. Only applicable for select filters. | |
selectConfig.multiple | false | false | Boolean | Whether or not the select should allow multiple selections. Only applicable for select filters. | 
placeholder | false | String | The placeholder to render for the filter. | 
Events
| Event Name | Reach Event Name | Payload | Description | 
|---|---|---|---|
ecc-utils-page-change | EccUtilsPageChangeEvent | { page: Number } | Fired when the page is changed. | 
ecc-utils-expand | EccUtilsExpandEvent | { key: String } | Fired when an item is expanded. | 
ecc-utils-filter | EccUtilsFilterEvent | { key: String, value: String } | Fired when a filter is applied. | 
Methods
| Method Name | Arguments | Description | 
|---|---|---|
setPage() | page | Can be used to set the page of the collection. | 
error() | message | Can be used to display error alert to the user. | 
Slots
| Slot Name | Description | 
|---|---|
${items.key} | The contents of the item. This slot will be named after the key of the item provided by the items property. | 
Parts
🔫
 Bro! We are working!
CSS Variables
💣
 Under construction.