Our blazing fast Grid component built with pure JavaScript


Post by caspernh »

I am trying to setup a AjaxStore in my Laravel / Vue3 application.

Currently I have the code below as my store. This initially loads the data into the grid, but i dont trigger any requests when changing the data. (fx. delete or copy records)

const store = new AjaxStore({
    readUrl: 'diagnoses/index-data',
        createUrl: 'diagnoses/submit',
    updateUrl  : 'diagnoses/update',
    deleteURL: 'diagnoses/delete',

autoLoad: true,
fields : [
{ type : 'date', name : 'updated_at', format : DATE_FORMAT, serialize  : serializeDate },
{ type : 'date', name : 'created_at', format : DATE_FORMAT, serialize  : serializeDate }
]

});

Can you point me in the direction of a example where AjaxStore is used to retreive and sync data?


Post by mats »

Sounds like your records don't have 'id' set? Can you please share your data?


Post by caspernh »

Hi Mats

I check the ID, i seem to have this set. Maybe you can see the problem in the code below.

<template>
    <app-layout title="Diagnoser">


    <template #header>
        <div class="flex md:justify-between justify-end">

            <breadcrumbs :paths="[{name: 'Diagnoser',route: 'diagnoses.index'}, ]"></breadcrumbs>


            <div class="flex items-center">


                <button class="v-button v-button-help v-button-header h-full" @click="toggleColumn">
                  Toogle Status column
                </button>

                    <button class="v-button v-button-help v-button-header h-full" @click="openSupportDocumentModal">
                        <QuestionMarkCircleIcon class="h-5 w-5 text-gray-500 mr-1"/> Hjælp
                    </button>

                    <button class="v-button v-button-primary v-button-header h-full" @click="openCreateDiagnoseModal">
                        <PlusIcon class="h-5 w-5 text-white mr-1"/> Ny diagnose
                    </button>

            </div>

        </div>
    </template>


        <div class="max-w-7xl mx-auto px-0 sm:px-6 lg:px-8 w-full">

                <bryntum-grid
                    ref="grid"
                    v-bind="gridConfig"
                    class="h-full"
                    @datachange="syncData"
                />

                <create-diagnose-modal
                    ref="NewDiagnoseModal"
                    @diagnoseAdd="diagnoseAdd"
                />


            <support-document-modal ref="SupportDocumentModal"></support-document-modal>

        </div>

</app-layout>
</template>

<script>
import { defineComponent } from 'vue'
import AppLayout from '@/Layouts/AppLayout.vue'
import CreateDiagnoseModal from "@/Components/CreateDiagnoseModal";
import { BryntumGrid } from '@bryntum/grid-vue-3';
import { Grid, Toast, DataGenerator, DateHelper, AjaxStore } from '@bryntum/grid';


import { StringHelper } from '@bryntum/grid';
import Breadcrumbs from "@/Components/BreadcrumbsComponent";

import SupportDocumentModal from "@/Components/SupportDocumentModal";

import '/home/user/dev.vetma.dk/node_modules/@bryntum/grid/source/lib/Grid/column/DateColumn.js';
import '/home/user/dev.vetma.dk/node_modules/@bryntum/grid/source/lib/Core/widget//DateTimeField.js';

import { PlusIcon, QuestionMarkCircleIcon } from '@heroicons/vue/solid'


import zipcelx from 'zipcelx';


const
    DATE_FORMAT = 'YYYY-MM-DD',
    serializeDate = (value) => DateHelper.parse(value, DATE_FORMAT);


const store = new AjaxStore({
    readUrl: 'diagnoses/index-data',
        createUrl: 'diagnoses/submit',
    updateUrl  : 'diagnoses/update',
    deleteURL: 'diagnoses/delete',

autoLoad: true,
fields : [
{ type : 'date', name : 'updated_at', format : DATE_FORMAT, serialize  : serializeDate },
{ type : 'date', name : 'created_at', format : DATE_FORMAT, serialize  : serializeDate }
]

});


export default defineComponent({
    components: {
        AppLayout,
        BryntumGrid,
        Breadcrumbs,
        CreateDiagnoseModal,
        PlusIcon,
        QuestionMarkCircleIcon,
        SupportDocumentModal,
        DateHelper,
        DataGenerator,
        Toast,
        Grid


},

methods:{

    syncData({ store, action, records }) {

        console.log("fdfdsfdsdfs");

        console.log(`${store.id} changed. The action was: ${action}. Changed records: `, records);
   
    },

 
    toggleColumn() {


        const grid = this.$refs.grid.instance.value;

        if (grid.columns.get('status').hidden == true){
            grid.columns.get('status').hidden = false;
        }
        else {
            grid.columns.get('status').hidden = true;

        }
    },


    gridExportToExcel: function(){

        this.$refs.grid.instance.value.features.excelExporter.export();

        // this.$refs.grid.instance.value.features.excelExporter.export({
        //     exporterConfig: {
        //         columns: [
        //             {text: 'Indikation Navn', field: 'indication.name', width: 90},
        //         ]
        //     }
        // });

    },




},


props: [
    'diagnoses',
],

data() {
    return {

        gridConfig: {

            store: store,


            bbar : {
                type : 'pagingtoolbar' //pagination toolbar
            },

  
            features: {

                excelExporter : {
                    zipcelx
                },

                filterBar: {
                    compactMode: false,
                },

                stripe: true,
                quickFind: true
            },

            columns: [
                {type: 'rownumber', locked: true, hidden:true},
                {text: 'Id', field: 'id', flex: 2, hidden: true, editor: false},

  
                {
                    text: 'Diagnose',
                    field: 'name',
                    autoWidth: 1,
                    locked : true,
                    htmlEncode : false,
                    renderer({ record }) { return '<a href="diagnoses/' + record.id  + '">' + record.name + '</a>'}
                },
                {field: 'updated_by.name', text: 'Opdateret af', flex: 0, hidden: true, editor: false},
                {field: 'created_by.name', text: 'Oprettet af', flex: 0, hidden: true, editor: false},

                {field: 'updated_at',  type : 'date', text: 'Senest opdateret', autoWidth: 1,  editor : false, format : 'DD-MM-YYYY'},
                {field: 'created_at', type : 'date', text: 'Oprettelsesdato', flex: 0, hidden: true, editor: false, format : 'DD-MM-YYYY'},

                {
                    text: 'Status',
                    field: 'status',
                    maxWidth: '50',
                    align: 'center',
                    htmlEncode: false,
                    renderer({value}) {

                        if (value == 1) {
                            let color = "#accd85"
                            return StringHelper.xss`<div class="b-fa b-fa-circle" style="color: ${color};font-size: 1.5em"></div>`;
                        } else {
                            let color = "#eee"
                            return StringHelper.xss`<div class="b-fa b-fa-circle" style="color: ${color};font-size: 1.5em"></div>`;
                        }

                    }
                }

            ],

        }
    }
}

})
</script>
<style lang="scss">
@import "~@bryntum/grid/grid.stockholm.css";
@import '~@bryntum/demo-resources/scss/example.scss';
</style>

Post by mats »

Unless you call commit() manually, it won't save changes automatically, for this you have to set autoCommit

const store = new AjaxStore({
    readUrl: 'diagnoses/index-data',
        createUrl: 'diagnoses/submit',
    updateUrl  : 'diagnoses/update',
    deleteURL: 'diagnoses/delete',

autoLoad: true,
autoCommit: true,
});

https://bryntum.com/docs/scheduler/api/Core/data/AjaxStore#config-autoCommit


Post by caspernh »

I use Vue Dev tools and would expect to see all the events triggered here.
I use Vue Dev tools and would expect to see all the events triggered here.
events.png (25.03 KiB) Viewed 935 times

The autoCommit now triggered a request when copy and paste and delete. With that said, i'll properply have to handle events manually, as I use axios for request to server.

I can see that the grid has multiple events like:
onBeforeCopy
onBeforeDestroy
onDataChange
onDestroy

Found in: \node_modules\@bryntum\grid-vue-3\src

I haven't been able to catch any of these events and run my custom methods. Can you show me how this works?

I tried to listen for the events like shown below. But as far as I can see no events is triggered.

                <bryntum-grid
                        ref="grid"
                        v-bind="gridConfig"
                        class="h-full"
                        @onDataChange="syncData"
                        @onDestroy="syncData"
                        @beforepaste="syncData"
                    />

Post by alex.l »

Please see our guide here, with an example how to listen to datachange event https://bryntum.com/docs/grid/guide/Grid/integration/vue/guide#using-datachange-event-to-synchronize-data

<template>
        <bryntum-grid
            ref="grid"
            v-bind="gridConfig"
            @datachange="syncData"
        />
    </div>
</template>

Be aware, if you listen to destroy event on grid level, it will be destroy event for the grid itself, not for some record in the store, or what you expect to track by that.
datachange event will be triggered for all data changes you'll be needed to track, that should be enough to track.
Docs: https://bryntum.com/docs/grid/api/Grid/view/GridBase#event-dataChange

All the best,
Alex


Post by caspernh »

The missing response was casued by typo in the example provided

    <bryntum-grid
        ref="grid"
        v-bind="gridConfig"
       @datachange="syncData"
    />

should be:

    <bryntum-grid
        ref="grid"
        v-bind="gridConfig"
        @dataChange="syncData"
    />

Post by caspernh »

I am still very confused with this grid and how its used with Vue.

  1. I would like to catch events before they happen. Fx. on delete.
    I would like to wait for a response from the server before removing the record from the grid.

  2. Where do i place listeners on the grid.
    I would like to listen for any changes to selected records. (Trigger event when any item is selected)


Post by alex.l »

All available events are described in our docs. for store here: https://bryntum.com/docs/grid/api/Core/data/Store#events
For grid here: https://bryntum.com/docs/grid/api/Grid/view/Grid#events
You might be needed to review our examples as well in /examples/frameworks/vue folder.

There are 3 ways of how you can listen to events.

  1. Using vue notation for events that triggered on !grid! level, we have in our guide and examples:
            <bryntum-grid
                ref="grid"
                v-bind="gridConfig"
                @selectionchange="onSelectionChange"
            />
    

selectionchange is an event name https://bryntum.com/docs/grid/api/Grid/view/Grid#event-selectionChange
It works the same for all others !grid! level events.

  1. Pass listeners with gridConfig, using listeners object. https://bryntum.com/docs/grid/api/Core/mixin/Events#config-listeners
    AppConfig.js
    const gridConfig = {
        columns: [
            {
                text: 'First name',
                field: 'firstName',
                flex: 1
            },
    // ...
       ],
       // for grid level events
       listeners : {
           selectionChange() {
                console.log('Do soemthing here');
           }
       },
       // for store events
       store : {
            data : data,
            listeners : {
                beforeAdd({ records, source }) {
                    if (records[0].name === 'Mark') {
                        return false;
                    }
                    return true;
                }
            }
       }
    
  1. Add listeners on instance level.
  setup() {
        const grid = ref(null);
     
onMounted(() => { const gridInstance = grid.value.instance; gridInstance.on('selectionchange', ()=>{ console.log('selection has been changed') }); gridInstance.store.on('change', () => { console.log('store changed') }); });

All the best,
Alex


Post by caspernh »

Hi Alex. Thanks you usefull feedback. I'll try out these examples.


Post Reply