logo polydile logo polydile en modo oscuro dile-components

dile-crud-list

The dile-crud-list component is designed to list existing elements in a REST API resource. It is a sophisticated component with multiple customization options to adapt to various needs and web service configurations.

The component allows you to create lists of resource elements, with or without pagination, provide various controls on the items, such as edit and delete buttons, as well as apply filters and different sorting options, among other features.

Installation

npm i @dile/crud

Usage

Import the dile-crud-list component.

import '@dile/crud/components/list/crud-list.js';

Use the component.

<dile-crud-list
  .config=${this.config}
></dile-crud-list>

Properties

Methods

Events

Configuration

This component requires a configuration object with numerous properties, methods, and templates to customize its behavior, functionality, and appearance.

Complete information on how to configure it easily can be found on the general CRUD guides page. Also, you can find implementation examples below.

To simplify the use of CRUD components, the configuration object required is the same for all the various CRUD components, such as lists, fully functional CRUD pages, or detail pages for a record.

Unpaginated List Example

Create configuration object for a resource

Before looking at implementation examples of lists, it’s important to understand how to build configuration objects, as they are absolutely necessary for centrally providing the parameters needed to customize functionality.

You can learn how to create configuration objects on the page that explains the resource configuration object.

<script type="module">
import { html } from 'lit';
import { CrudConfigBuilder } from '@dile/crud/lib/CrudConfigBuilder';
import '@dile/ui/components/pages/pages';

// For the correct functioning of this declaration in the demo system, we have defined the variable with the configuration object globally. Normally, it would be created in a module and exported.
window.countryConfig = new CrudConfigBuilder('https://timer.escuelait.com/api/countries', {
  templates: {
    item: (country) => html`<demo-country-item .country=${country}></demo-country-item>`,
    insertForm: () => html`<demo-country-form id="insertform"></demo-country-form>`,
    updateForm: () => html`<demo-country-form id="updateform"></demo-country-form>`,
    help: () => html`<p>This is the help provided to the countries resource.</p>`,
    detail: (country) => html`<demo-country-detail .country="${country}"></demo-country-detail>`,
    relations: (country) => html`<demo-country-relations .country=${country}></demo-country-relations>`,
    formSingleActions: (actionName, country) => html`
        <dile-pages attrForSelected="action" selected="${actionName}">
            <demo-set-europe-as-continent-action action="SetEurope" .country=${country}></demo-set-europe-as-continent-action>
            <demo-set-asia-as-continent-action action="SetAsia" .country=${country}></demo-set-asia-as-continent-action>
        </dile-pages>
    `,
  },
  customization: {
    disablePagination: true,
    disableHelp: false,
    disableKeywordSearch: false,
    disableSort: false,
    disableFilter: false,
  },
  actions: {
    single: [
      {
        name: "SetEurope",
        label: "Set Europe as continent"
      },
      {
        name: "SetAsia",
        label: "Set Asia as continent"
      },
    ]
  },
  labels: {
    helpTitle: 'Country help',
  },
  sort: {
    options: [
      {
        name: 'name',
        label: 'Name',
        direction: 'desc'
      },
    ],
    initialSortField: 'name',
  },
  availableFilters: [
      {
        name: 'continent',
        label: 'Continent',
        active: false,
        value: false,
        type: 'select',
        options: [
            {
                name: 'Europe',
                label: 'Europe'
            },
            {
                name: 'Africa',
                label: 'Africa'
            },
            {
              name: 'Asia',
              label: 'Asia'
          },
        ]
      },
    ],
});
</script>

Create a item Component

The list components require a template to implement the list items. This template typically uses a component that receives the item object as an attribute to render it.

In this first example, you can find the implementation of a list item.

<script type="module">
import { LitElement, html, css } from 'lit';

export class DemoCountryItem extends LitElement {
  static styles = [
    css`
      :host {
        display: block;
        color: #303030;
      }
      span {
        font-style: italic;
        font-size: 0.9rem;
      }
    `
  ];

  static get properties() {
    return {
      country: { type: Object }
    };
  }

  render() {
    return html`
      ${this.country.name} - 
      <span @click=${this.dispatchContinent}>${this.country.continent}</span>
    `;
  }

  dispatchContinent() {
    this.dispatchEvent(new CustomEvent('continent-event', { 
      bubbles: true,
      composed: true,
      detail: this.country
    }));
  }
}
customElements.define('demo-country-item', DemoCountryItem);
</script>

Unpaginated list component

This is a simple list component without pagination. When the edit and delete icons are clicked, messages will be displayed in the console.

Additionally, clicking the name of the continent in each country's item will also log a message to the console. This continent event demonstrates that item components can have their own behaviors and events, which can be handled by the components implementing the lists.

<script type="module">
  import { LitElement, html, css } from 'lit';
  import '@dile/crud/components/list/crud-list.js'
  
  class DemoCountryList extends LitElement {
    static styles = [
      css`
        :host {
          display: block;
        }
      `
    ];

    static get properties() {
      return {
        config: { type: Object },
      };
    }

    constructor() {
      super();
      // The countryConfig variable has been defined globally to simplify this demo. Ideally, it should be imported from a module.
      this.config = window.countryConfig.getConfig();
    }

    render() {
      return html`
        <dile-crud-list
          @continent-event=${this.showOnConsole}
          @crud-item-edit=${this.showOnConsole}
          @crud-item-delete=${this.showOnConsole}
          .config="${this.config}"
        ></dile-crud-list>
      `;
    }

    showOnConsole(e) {
      console.log(e.detail);
    }

  }
  customElements.define('demo-country-list', DemoCountryList);
</script>
<demo-country-list></demo-country-list>

Paginated List Example

Create configuration object for a resource

Configuration objects creation are explained on the page that explains the resource configuration object.

<script type="module">
import { html } from 'lit';
import { CrudConfigBuilder } from '@dile/crud/lib/CrudConfigBuilder';
import { ResponseApiAdapter } from '@dile/crud/lib/ResponseApiAdapter';

class BoardGameResponseApiAdapter extends ResponseApiAdapter {
  getElementList() {
    return this.response.data.result.data;
  }
}
// For the correct functioning of this declaration in the demo system, we have defined the variable with the configuration object globally. Normally, it would be created in a module and exported.
window.boardGameConfig = new CrudConfigBuilder('https://timer.escuelait.com/api/board-games', {
  customization: {
    hideCountSummary: false,
    hideCheckboxSelection: false,
    disablePagination: false,
    disableHelp: true,
    disableKeywordSearch: false,
    disableSort: false,
    disableFilter: false,
  },
  sort: {
    options: [
      {
        name: 'name',
        label: 'Name',
        direction: 'asc'
      },
      {
        name: 'year',
        label: 'Year',
        direction: 'desc'
      },
    ],
    initialSortField: 'year',
  },
  availableFilters: [
    {
      name: 'essential',
      label: 'Is essential',
      active: false,
      value: false,
      type: 'boolean',
    },
  ],
  responseAdapter: new BoardGameResponseApiAdapter(),
  actions: {
    list: [
      {
        label: 'Delete board games',
        name: 'DeleteAction'
      },
      {
        label: 'Change Essential',
        name: 'DemoChangeEssentialAction'
      },
    ],
  },
  templates: {
    item: (boardGame) => html`<demo-board-game-item .boardGame=${boardGame}></demo-board-game-item>`,
    insertForm: (belongsTo, relationId) => html`<demo-board-game-form id="insertform" belongsTo="${belongsTo}" relationId="${relationId}"></demo-board-game-form>`,
    updateForm: () => html`<demo-board-game-form id="updateform"></demo-board-game-form>`,
    formActions: (actionName, actionIds) => html`
        <dile-pages attrForSelected="action" selected="${actionName}">
            <dile-crud-delete-action action="DeleteAction"></dile-crud-delete-action>
            <demo-change-essential-action action="DemoChangeEssentialAction" .actionIds=${actionIds}></demo-change-essential-action>
        </dile-pages>
    `,
  },
});
</script>

Create a item Component

This components acts as a template for the list items.

<script type="module">
import { LitElement, html, css } from 'lit';

export class DemoBoardGameItem extends LitElement {
  static styles = [
    css`
      :host {
        display: block;
        color: #303030;
      }
    `
  ];

  static get properties() {
    return {
      boardGame: { type: Object }
    };
  }

  render() {
    return html`
      ${this.boardGame.name} - (${this.boardGame.year})
    `;
  }
}
customElements.define('demo-board-game-item', DemoBoardGameItem);
</script>

Paginated list component

The use of paginated lists primarily differs in the definition of a different configuration object, which has additional requirements.

<script type="module">
import { LitElement, html, css } from 'lit';

export class DemoBoardGameList extends LitElement {
  static styles = [
    css`
      :host {
        display: block;
      }
    `
  ];

  static get properties() {
    return {
      config: { type: Object },
    };
  }

  constructor() {
    super();
    this.config = window.boardGameConfig.getConfig();
  }

  render() {
    return html`
      <dile-crud-list
        .config="${this.config}"
        pageSize="15"
      ></dile-crud-list>
    `;
  }

}
customElements.define('demo-board-game-list', DemoBoardGameList);
</script>
<demo-board-game-list></demo-board-game-list>