logo polydile logo polydile en modo oscuro dile-components

dile-crud-single

The dile-crud-single component is designed to display the details of a record from a REST API, along with the available actions for it and any related resources.

Installation

npm i @dile/crud

Usage

Import the dile-crud component.

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

Use the component.

<dile-crud-single
  relatedId="1"
  .config="${this.config}"
></dile-crud-single>

Properties

Methods

Events

This component is built on multiple components from the @dile/crud catalog. As a result, it can dispatch a large number of events, such as those detailed in dile-crud, dile-crud-update, dile-crud-item-delete, and others.

Particularly useful events include:

Refer to the documentation of other components to discover many more events available in dile-crud-single.

Configuration

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

Examples

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>

Resource form component

The resource form provides the necessary fields for editing the record.

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>

Detail template component

Technically, it's not necessary to build a component to define the details of the item you want to display, as a simple template would be enough. However, to keep things organized and reusable, you would typically use a component dedicated to displaying the details, which also allows you to include additional functionality if needed.

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

export class DemoCountryDetail extends LitElement {
  static styles = [
    css`
      :host {
        display: block;
        color: #303030;
      }
      p {
        margin: 0 0 1rem;
      }
      .last {
        margin-bottom: 0;
      }
    `
  ];

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

  render() {
    return html`
      <p>Name: ${this.country.name}</p>
      <p class="last">Continent: ${this.country.continent}</p>
    `;
  }
}
customElements.define('demo-country-detail', DemoCountryDetail);
</script>

Action components

Some actions that can be performed from the crud-single component include:

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

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

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

  render() {
    return html`
    <p>Do you really want to set Europe as continent of ${this.country?.name}?</p>
    `;
  }
}
customElements.define('demo-set-europe-as-continent-action', DemoSetEuropeAsContinentAction);


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

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

  render() {
    return html`
    <p>Do you really want to set Asia as continent of ${this.country?.name}?</p>
    `;
  }
}
customElements.define('demo-set-asia-as-continent-action', DemoSetAsiaAsContinentAction);
</script>

Component for Relationships

The single pages of a CRUD can display records of related entities using dile-crud components, filtered by the belongsTo and relationId properties.

For this relationship to work, we need the components required by the board games CRUD itself.

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

<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

The board game custom batch action.

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

Single relations component

This is the component that allows you to define relationships. In this component, we use a dile-crud, but technically you could include any type of content.

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

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

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

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

  firstUpdated() {
    console.log(this.country);
  }

  render() {
    return html`
    ${this.country
      ? html `
        <dile-crud
          title="Juegos de ${this.country.name}"
          .config="${this.boardGameConfig}"
          belongsTo="country"
          relationId="${this.country.id}"
        ></dile-crud>  
      `
      : ''
    }
    
    `;
  }
}
customElements.define('demo-country-relations', DemoCountryRelations);
</script>

Crud single Component

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

export class DemoCountrySingle 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-single
        relatedId="1"
        .config="${this.config}"
      ></dile-crud-single>
    `;
  }
}
customElements.define('demo-country-single', DemoCountrySingle);
</script>
<demo-country-single></demo-country-single>