logo dile-components dile-components

dile-many-relation

The dile-many-relation component provides a generic front-end interface for managing many-to-many relationships. It displays the currently associated items and allows users to add new ones via a searchable select or remove existing ones, all backed by REST API endpoints.

It is designed to work with any pair of entities. A typical use case would be managing the Tags associated with a Board Game from the Board Game detail page.

Installation

npm i @dile/crud

Usage

Import the component:

import '@dile/crud/components/many-relation/many-relation.js';

Basic usage:

<dile-many-relation
  endpointGet="/api/tags"
  endpointList="/api/board-games/1/tags"
  endpointAdd="/api/board-games/1/tags"
  endpointRemove="/api/board-games/1/tags"
  idProperty="id"
  bodyIdProperty="tag_id"
  displayProperty="name"
  resultDataProperty="data"
  loadFromEndpoint
  language="en"
></dile-many-relation>

Properties

Endpoints

Initial data

Select configuration (passed to the internal dile-ajax-select-crud)

List customisation

Custom events

Styling

Custom property Description Default
--many-relation-item-font-size Font size of each related item label 0.9rem
--many-relation-item-color Text color of each related item label inherit
--many-relation-add-size Size of the add icon button (also controls the width of all icon columns for alignment) 38px
--many-relation-add-color Color of the add icon #2962ff
--many-relation-add-disabled-color Color of the add icon when no item is selected #ccc
--many-relation-remove-size Size of the remove icon 22px
--many-relation-remove-color Color of the remove icon #c00
--many-relation-empty-font-size Font size of the empty list message 0.9rem
--many-relation-empty-color Text color of the empty list message #888
--many-relation-empty-font-style Font style of the empty list message italic

The component also uses dile-ajax-select-crud, dile-icon, and dile-spinner internally, so their respective CSS custom properties are also available.

dile-many-relation Demo

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

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

  static get properties() {
    return {
      gameId: { type: Number },
    };
  }

  constructor() {
    super();
    this.gameId = 1;
  }

  render() {
    return html`
      <dile-ajax-select-crud
        idProperty="id"
        name="game_id"
        label="Board Game"
        endpoint="https://timer.escuelait.com/api/board-games"
        queryStringVariable="keyword"
        value="${this.gameId}"
        placeholder="Search board game..."
        .getSelectResultList=${(response) => response.data.result.data}
        displayProperty="name"
        selectDefaultPlaceholder="Select board game..."
        @element-changed=${this.onGameChanged}
      ></dile-ajax-select-crud>

    ${this.gameId 
      ? this.relationTemplate
      : 'Select board game...'
    }
    `;
  }
  get relationTemplate() {
    return html`
      <dile-form-separator label="dile-many-relation component in action"></dile-form-separator>
      <dile-many-relation
        endpointGet="https://timer.escuelait.com/api/tags"
        endpointList="https://timer.escuelait.com/api/board-games/${this.gameId}/tags"
        endpointAdd="https://timer.escuelait.com/api/board-games/${this.gameId}/tags"
        endpointRemove="https://timer.escuelait.com/api/board-games/${this.gameId}/tags"
        idProperty="id"
        bodyIdProperty="tag_id"
        displayProperty="name"
        resultDataProperty="data"
        loadFromEndpoint
        language="en"
        .itemTemplate=${(item) => html`<b>${item.name}</b>`}
      ></dile-many-relation>
    `
  }
  onGameChanged(e) {
    this.gameId = e.detail.value;
  }
}
customElements.define('demo-many-relation', DemoManyRelation);
</script>
<demo-many-relation></demo-many-relation>