Lattice Grid Buy a licence

demo D218

The form, four ways

The same row form as a drawer, a dialog, an inline region and a curated set

rowForm: { mode: 'drawer' · 'dialog', container }

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.28.0/lattice-grid.min.css">
<style>
  #buttons { display: flex; gap: 8px; margin-bottom: 12px; }
  #panes { display: flex; gap: 14px; }
  #grid { flex: 1; }
  #grid > div { height: 520px; }
  #inline-form { width: 320px; }
</style>
<div id="app"></div>

<script type="module">
  import * as Vue from 'https://esm.sh/vue@3';
  import { createGrid } from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.28.0/lattice-grid.esm.min.js';
  import createLatticeGrid from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.28.0/modules/vue.esm.min.js';

  const LatticeGrid = createLatticeGrid({ vue: Vue, createGrid });

  Vue.createApp({
    components: { LatticeGrid },
    data() {
      const fields = [
        { field: 'service', label: 'Service' },
        { field: 'team', label: 'Team' },
        { field: 'region', label: 'Region' },
        { field: 'tier', label: 'Tier' },
        { field: 'instances', label: 'Instances' },
        { field: 'monthlyCost', label: 'Monthly cost' },
        { field: 'notes', label: 'Notes', editor: 'textarea' },
      ];
      return {
        mode: 'drawer',
        // The same form, placed four ways. Only the rowForm option differs:
        //   drawer - a right-hand panel (the default)
        //   dialog - a centred modal
        //   inline - built into an element of your own; a region, not a modal
        //   curated - the drawer with a chosen few fields
        modes: {
          drawer:  { mode: 'drawer', title: 'Edit service', fields },
          dialog:  { mode: 'dialog', title: 'Edit service', fields },
          inline:  { fields, container: '#inline-form' },
          curated: { mode: 'drawer', title: 'Quick edit',
            fields: [{ field: 'tier', label: 'Tier' }, { field: 'instances', label: 'Instances' },
                     { field: 'notes', label: 'Notes', editor: 'textarea' }] },
        },
        columns: [
          { field: 'service', title: 'Service', layout: { pin: 'start', width: 150 } },
          { field: 'team', title: 'Team', filter: { type: 'set' } },
          { field: 'region', title: 'Region', filter: { type: 'set' } },
          { field: 'tier', title: 'Tier' },
          { field: 'instances', title: 'Instances', type: 'number' },
          { field: 'monthlyCost', title: 'Monthly cost', type: 'number', format: { style: 'currency', currency: 'USD' } },
        ],
      };
    },
    computed: {
      // rowForm is read when the grid is built, so keying the component on the mode
      // rebuilds it whenever the placement changes.
      config() {
        return { rowKey: 'id', editable: true, rowForm: this.modes[this.mode], columns: this.columns, rows };
      },
    },
    watch: {
      mode() {
        // Open it on the rebuilt grid so the placement shows.
        this.$nextTick(() => this.$refs.grid.grid().form.open(String(rows[0].id)));
      },
    },
    mounted() {
      this.$refs.grid.grid().form.open(String(rows[0].id));
    },
    template: `
      <div>
        <div id="buttons">
          <button v-for="name in Object.keys(modes)" :key="name" @click="mode = name">{{ name }}</button>
        </div>
        <div id="panes">
          <div id="grid"><lattice-grid :key="mode" ref="grid" v-bind="config" /></div>
          <div id="inline-form"></div>
        </div>
      </div>
    `,
  }).mount('#app');
</script>