npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

datagrid-bvue

v0.2.2

Published

DataGrid based on bootstrap vue

Downloads

124

Readme

Jest Tests on Node 16.x and 18.x

DataGrid

Provide Plugin for Grids (table with editable cells). And also components for filtering. This plugin use BootstrapVue.

For displaying tabular data, supports pagination, filtering, sorting, various style options, events, and asynchronous data.

  • [x] Vue.js v2.7.14 is recommended

  • [x] Bootstrap-vue is 2.23.1 recommended

  • [x] Bootstrap is 4.6.0 recommended

Table of Contents

Installation

Install with npm

npm install datagrid-bvue

Install with yarn

yarn add datagrid-bvue

Features

Available components:

Available features:

  • Pagination
  • Filtering
  • Sorting
  • Customizable
  • Asynchronous data
  • Custom field types
  • Custom rules components
  • Rules schemas
  • Decorators for models and fields
  • Customizable style
  • i18n translation (en, fr)

Demo folder

You can find a demo folder with a complete example. Demo

// Importing styles
import 'datagrid-bvue/style.css';
// Import Bootstrap and BootstrapVue CSS files (order is important)
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import 'bootstrap-vue/dist/bootstrap-vue-icons.min.css'

// setups the plugin with some options
import DataGridPlugin from 'datagrid-bvue'
Vue.use(DataGridPlugin, {
  ruleSchemas: {
    Student: [
      {identifier: 'id', name: 'id', type: 'String'},
      {identifier: 'firstName', name: 'Prenom', type: 'String'},
      {identifier: 'lastName', name: 'Nom', type: 'String'},
    ],
  },
})

can be initialised with custom field type viewers and editors

import CustomTypeViewer from './CustomFieldViewer.vue'
import CustomTypeEditor from './CustomEditor.vue'

Vue.use(DataGridPlugin, {
  lang: 'Fr', //default Fr
  calendarTime: false, //default true
  dateFormat: 'ddd DD-MM-YY HH:mm',
  customFieldTypes: [
    {name: 'SomeType', viewer: CustomTypeViewer, editor: CustomTypeEditor},
  ],
})

can be used with rules schema

Rules schemas allows you to use the Filter component.

Vue.use(DataGridPlugin, {
  lang: 'fr',
  ruleSchemas: {
    Student: [
      {identifier: 'id', name: 'id', type: 'String'},
      {identifier: 'firstName', name: 'Prenom', type: 'String'},
      {identifier: 'lastName', name: 'Nom', type: 'String'},
    ],
  },
})

The Filter component inject inside your provider ctx object a FilterRuleInterface Object.

Usage

Datagrid Table

Extra (provider function, fields type autodetect and pagination)

  • Autodetect fields type with correct edition component in the cell
  • Extra slot for actions
  • Provider for async data and Database connection
    • Generated pagination, can be also used with provider function by adding "paginationEntries" props. paginationEntries // number of total entries for pagination using provider function
<template>
  <div>
    <h1>{{ title }}</h1>
    <DataGridTable
      name="school"
      :items="provider"
      @goToEditor="goToItemEditor"
    />
  </div>
</template>

<script lang="ts">
import Vue, { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      title: 'Testing datagrid',
      items: [
        {
          id: 'Rebellious66',
          age: 53,
          first_name: 'Dragon',
          last_name: 'Monkey D.',
          da: new Date(),
          skills: [],
        },
      ],
    }
  },
  methods: {
    async provider(ctx) {
      //ctx
      return this.items
    },
    goToItemEditor(item) {
      const msg = 'open complete editor for item, ' + JSON.stringify(item)
      alert(msg)
    },
  },
})
</script>
  • Modification handler
<template>
  <div>
    <h1>{{ title }}</h1>
    <DataGridTable
      name="valhalla"
      :items="provider"
      @goToEditor="goToItemEditor"
      @modified="modificationStart"
      :modification-handler="modificationHandler"
    />
  </div>
</template>

<script lang="ts">
import Vue, { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      title: 'Testing datagrid',
      items: [
        {
          id: 'Rebellious66',
          age: 40,
          first_name: 'Ragnar',
          last_name: 'Lothbrok',
          da: new Date(),
          skills: [],
        },
      ],
    }
  },
  computed: {},
  methods: {
    // will call this function after each modification handler routine
    async provider(ctx) {
      // use ctx for api calls
      const delay = (ms) => new Promise((res) => setTimeout(res, ms))
      await delay(2000)
      return this.items
    },
    // can be used to prepare a route to edit page
    goToItemEditor(item) {
      const msg = 'open complete editor for item, ' + JSON.stringify(item)
      alert(msg)
    },
    // you can use a custom modification handler
    async modificationHandler({item, fieldKey, newValue}) {
      item[fieldKey] = newValue
    },
    modificationStart() {
      // a call to the modification handler was emitted
      console.log('modified')
    },
  },
  watch: {},
})
</script>
  • Other fields
<template>
  <div>
    <h1>{{ title }}</h1>
    <DataGridTable name="school" :items="items" :fields="fields" striped />
  </div>
</template>

<script lang="ts">
import Vue, { defineComponent } from 'vue'
import {Money} from 'ts-money/build'

export default defineComponent({
  data() {
    return {
      title: 'Testing page',
      items: [
        {
          id: 'aaa',
          a: 'hello_0',
          b: 'Fr',
          c: 10,
          d: 'M',
          e: null,
          f: new Money(1200, 'CAD'),
          g: [],
        },
        {
          id: 'bbb',
          a: undefined,
          b: 'fr',
          c: 78,
          d: '',
          e: {className: 'Invoice'},
          f: 89,
          g: [],
        },
        {id: 'ccc', h: '', i: 'QC', j: null},
      ],
      fields: [
        {
          identifier: 'id',
          name: 'Id title',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'String',
        },
        {
          identifier: 'a',
          name: 'message',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'String',
        },
        {
          identifier: 'b',
          name: 'Language',
          config: {
            isVisible: true,
            isWritable: true,
            showFilter: false,
            showInGrid: true,
            sortable: false,
          },
          type: 'Lang',
        },
        {
          identifier: 'c',
          name: 'Percent',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'Percent',
        },
        {
          identifier: 'd',
          name: 'Gender',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'Gender',
        },
        {
          identifier: 'e',
          name: 'Other',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'Pointer',
          onClickExternalRoutine: this.testPointerHandler,
        },
        {
          identifier: 'f',
          name: 'Account',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'Money',
        },
        {
          identifier: 'g',
          name: 'Courses',
          config: {
            canView: true,
            canRead: true,
            canEdit: false,
            canFilter: true,
            canSort: true,
          },
          type: 'Array',
        },
      ],
    }
  },
  methods: {
    async provider(ctx) {
      // const delay = ms => new Promise(res => setTimeout(res, ms));
      // await delay(3000)
      return this.items
    },
    async testPointerHandler(data) {
      // can be used to start move the page or notify an attempt to modify a pointer type
      console.log(data)
    },
  },
})
</script>

A usa as Table

B-Table style props available:

<template>
  <div>
    <h1>{{ title }}</h1>
    <DataGridTable
      name="school"
      :items="items"
      :fields="fields"
      @goToEditor="goToItemEditor"
    />
  </div>
</template>

<script lang="ts">
import Vue, { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      title: 'Testing datagrid',
      items: [
        {id: 'aaa', a: 1, b: 2, c: 3},
        {id: 'bbb', a: 4, b: 5, c: 6},
        {id: 'ccc', a: 7, b: 8, c: 9},
      ],
      fields: [
        {
          identifier: 'id',
          name: 'Id title',
          type: 'String',
        },
        {
          identifier: 'a',
          name: 'A',
          type: 'String',
        },
        {
          identifier: 'b',
          name: 'b',
          type: 'String',
        },
      ],
    }
  },
  methods: {
    goToItemEditor(item) {
      const msg = 'open complete editor for item, ' + JSON.stringify(item)
      alert(msg)
    },
  },
})
</script>

Actions slot

An action slot "#action" is available for each row. You can use it to add buttons or other actions.

<template #action="{item, index}">
  action slot
  {{ index }} {{ item }}
</template>
// add an extra field to use in the action slot
const fields = {
  identifier: '#action',
  name: 'Actions',
  config: {
    canView: true,
    canRead: true,
    canEdit: false,
    canFilter: true,
    canSort: true,
  },
  type: FieldType.String,
}

Rule Engine Filter

To use the filter you need to add the target name that matches the schema name

// config

Vue.use(DataGridPlugin, {
  ruleSchemas: {
    Student: [
      {identifier: 'id', name: 'id', type: 'String'},
      {identifier: 'firstName', name: 'Prenom', type: 'String'},
    ],
  },
})

// usage

<DataGridTable
  name="42 School"
  target="Student"
  :items="provider"
  :fields="fields"
/>
  • You can also use the filter as a standalone component
<RuleEngineFilter
  v-model="filterBuild"
  :field-list="authorisedFields"
  operator="AND"
  target="Student"
  visible-name="School"
/>

Modal Rule Creator

<template>
  <div class="my-4">
    <h2>{{ title }}</h2>
    <div class="d-inline-flex">
      <button class="btn btn-primary ml-4" @click="toggleModal">
        Toggle Modal
      </button>
      <button
        class="btn btn-primary ml-4"
        @click="
          () => {
            useEditor = !useEditor
          }
        "
      >
        Toggle custom editor
      </button>
    </div>
    <RuleEngineCreatorModal
      ref="mod"
      v-model="modalVisible"
      :use-editor="useEditor"
      :rule="filterBuild"
      target="Invoice"
      @update:rule="
        (filterEdited) => {
          filterBuild = filterEdited
        }
      "
    >
      <template v-slot:editor="{value, onEditorInput}">
        <div class="form-group">
          <label for="">Custom editor</label>
          <input
            type="text"
            class="form-control"
            :value="value"
            @input="(val) => onEditorInput(val.target.value)"
          />
        </div>
      </template>
    </RuleEngineCreatorModal>
  </div>
</template>

<script lang="ts">
import Vue, { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      title: 'Rule Creation Modal Tester',
      filterBuild: null,
      modalVisible: false,
      useEditor: false,
    }
  },
  methods: {
    toggleModal() {
      this.$refs.mod.toggleModal()
    },
  },
})
</script>

Model decorators

DatagridBvue offers powerful model decorators to streamline the setup of your grid data and configurations.

@DataGridModel() Marks the class as a model for the data grid system. @DataGridField(type: string, options?: FieldOptions)

Usage:


@DataGridModel()
export class Discount {
  @DataGridField('String')
  id!: string;

  @DataGridField('String')
  name!: string;

  @DataGridField('Number')
  value!: number;
}

@DataGridModel()
export class Invoice {
  @DataGridField('Money')
  total!: number;

  @DataGridField('InvoiceStatus')
  status!: string;

  @DataGridField('Date')
  createdAt!: unknown;

  @DataGridField('Pointer', { linkedEntityClass: Discount })
  discount!: Discount | undefined;
}

@DataGridModel()
class Student {
    @DataGridField()
    id: string;
    
    @DataGridField()
    firstName: string;
    
    @DataGridField()
    lastName: string;
    
    @DataGridField('Pointer', { linkedEntityClass: Invoice })
    invoice!: Invoice | undefined;
}

Utility:

  • getAllGridRulesConfig() - Returns a record object where keys are entity labels and values are an array of schema definitions for those entities. Can be used to setup the ruleSchemas option for the plugin.
  const options: DataGridOptions = {
      ...
      ruleSchemas: getAllGridRulesConfig(),
  }
  • getFieldsForEntity(entityClass: DataGridModelClass) - Fetches the fields for a given entity class.
  • getAllRegisteredEntitiesData - Fetches all the registered entities data.
  • getAllRegisteredModelIdentifiers - Fetches the identifiers for all registered entity models.
  • getFieldsForEntityId(entityId: string) - Fetches the fields for a given entity id.
  • getFieldsForEntityLabel(entityLabel: string) - Fetches the fields for a given entity label.
  • getAllGridFieldsConfig() - Returns a record object where keys are entity labels and values are an array of field data for those entities.