logo polydile logo polydile en modo oscuro dile-components

dile-crud

The dile-crud component is the primary tool for building the CRUD system, combining various components from this library to implement the full functionality of a create, read, update, and delete (CRUD) system.

Additionally, dile-crud also offers batch operation management through the definition of action components.

Installation

npm i @dile/crud

Usage

Import the dile-crud component.

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

Use the component.

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

Properties

Methods

Events

This component is based on elements such as dile-crud-list, dile-crud-insert, dile-crud-update, dile-crud-item-delete, and many others. Therefore, all events documented in those components can be listened to in dile-crud. Please refer to the mentioned components for information on those events.

Eventos específicos de dile-crud:

Configuration

Please refer to the general documentation on the CRUD library to find the established mechanisms for configuring the dile-crud component.

belongTo and relationId configuration

These fields facilitate the implementation of a type of filtering on the items that a dile-crud component will allow you to manage. For example, if you are trying to view invoices for the customer with id=10, belongsTo would be set to "customer" and relationId would be set to "10."

This is useful, for example, for managing a specific record on an admin page, like those that can be created using the dile-crud-single component. For instance, when viewing the details of a country, you could use a dile-crud component configured with belongsTo and relationId to manage all the states within that country directly from the dile-crud-single component.

Note that these configurations must be supported by the backend. The listing component will handle sending the necessary query strings to the backend, ensuring that the records delivered for the listings in this dile-crud component are properly filtered.

Unpaginated Crud Example

For the correct functioning of the dile-crud component, a configuration object is required. Depending on the functionalities requested through the configuration object, various additional components from the CRUD library may also be needed.

Configuration object

Find the guides for creating the configuration object on the resource configuration page.

<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>

Item component

The item component serves as a template to display each of the elements in the list.

<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>

Resource form component

The resource form provides the necessary fields for adding new elements to the resource. In this example, the same form is used for both insertions and edits, but it is possible to have a different form for each operation.

Instructions on how to create these forms can be found in the dile-crud-insert and dile-ajax-form component documentation.

<script type="module">
import { LitElement, html, css } from 'lit';
import '@dile/ui/components/input/input.js';
import '@dile/ui/components/select/select.js';
import { DileForm } from '@dile/ui/mixins/form'

export class DemoCountryForm extends DileForm(LitElement) {
  static styles = [
    css`
      :host {
        display: block;
      }
    `
  ];

  render() {
    return html`
      <dile-input label="Country name" name="name" id="name" hideErrorOnInput></dile-input>
      <dile-input label="Slug" name="slug" id="slug" hideErrorOnInput></dile-input>
      <dile-select name="continent" id="continent" label="Continent" hideErrorOnInput>
        <select slot="select">
          <option value="">Select...</option>
          <option value="Europe">Europa</option>
          <option value="South America">América del Sur</option>
          <option value="North America">Norte América</option>
          <option value="Asia">Asia</option>
          <option value="Africa">Africa</option>
          <option value="Oceania">Oceania</option>
        </select>
      </dile-select>
    `;
  }
}
customElements.define('demo-country-form', DemoCountryForm);
</script>
<demo-country-form></demo-country-form>

Crud component

<script type="module">
import { LitElement, html, css } from 'lit';
import '@dile/crud/components/crud/crud';

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

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

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

  render() {
    return html`
      <dile-crud
        .config="${this.config}"
      ></dile-crud>
    `;
  }
}
customElements.define('demo-country-crud', DemoCountryCrud);
</script>
<demo-country-crud></demo-country-crud>

Paginated Crud Example

Configuration object

Find the guides for creating the configuration object on the resource configuration page.

<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>

Item component

The item component serves as a template to display each of the elements in the list.

<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>

Resource form component

The resource form provides the necessary fields for adding new elements to the resource. In this case, the same form is used for both insertions and edits, but it is possible to have a different form for each operation.

Instructions on how to create these forms can be found in the dile-crud-insert component documentation and dile-ajax-form.

<script type="module">
import { LitElement, html, css } from 'lit';
import '@dile/ui/components/input/input.js';
import '@dile/ui/components/input/input-integer.js';
import '@dile/ui/components/checkbox/checkbox.js';
import '@dile/crud/components/ajax-select-crud/ajax-select-crud';

import { DileForm } from '@dile/ui/mixins/form'

export class DemoBoardGamesForm extends DileForm(LitElement) {
  static styles = [
    css`
      :host {
        display: block;
      }
    `
  ];

  static get properties() {
    return {
      belongsTo: { type: String },
      relationId: { type: String },
    };
  }

  firstUpdated() {
    if(this.belongsTo == "country" && this.relationId) {
      this.shadowRoot.getElementById('countryselect').value = this.relationId;
    }
  }

  render() {
    return html`
      <dile-input label="Nombre" name="name" id="name" hideErrorOnInput></dile-input>
      <dile-input label="Slug" name="slug" id="slug" hideErrorOnInput></dile-input>
      <dile-input-integer name="year" label="Year" hideErrorOnInput id="year"></dile-input-integer>
      <dile-ajax-select-crud
          id="countryselect"
          idProperty="id"
          name="country_id"
          label="País"
          endpoint="https://timer.escuelait.com/api/countries" 
          queryStringVariable="keyword"
          placeholder="Buscar país"
          resultDataProperty="data"
          displayProperty="name"
          selectDefaultPlaceholder="Seleccionar país..."
      ></dile-ajax-select-crud>
      <p><dile-checkbox name="essential">Essential</dile-checkbox></p>
    `;
  }
}
customElements.define('demo-board-game-form', DemoBoardGamesForm);
</script>
<demo-board-game-form></demo-board-game-form>

Action component

For the purposes of this CRUD component demo, we will include a custom batch action.

You can find more information about actions in the actions section of the CRUD documentation.

<script type="module">
import { LitElement, html, css } from 'lit';
import { DileForm } from '@dile/ui/mixins/form';
import '@dile/ui/components/select/select.js';

export class DemoChangeEssentialAction extends DileForm(LitElement) {
  static styles = [
    css`
      :host {
        display: block;
      }
    `
  ];

  static get properties() {
    return {
      actionIds: { type: Array }
    };
  }

  constructor() {
    super();
    this.actionIds = [];
  }

  render() {
    return html`
      <p>Change essential game state of ${this.actionIds.length} elements.</p>
      <dile-select name="essential">
        <select slot="select">
          <option value="0">Not Essential</option>
          <option value="1">Essential</option>
        </select>
      </dile-select>
    `;
  }
}
customElements.define('demo-change-essential-action', DemoChangeEssentialAction);
</script>

Crud component

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

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

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

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

  render() {
    return html`
      <dile-crud
        .config="${this.config}"
      ></dile-crud>
    `;
  }
}
customElements.define('demo-board-game-crud', DemoBoardGameCrud);
</script>
<demo-board-game-crud></demo-board-game-crud>