[VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Our pure JavaScript Scheduler component


Post Reply
User avatar
sactory
Premium Member
Premium Member
Posts: 73
Joined: Mon Jun 01, 2020 4:06 am

[VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by sactory »

Hello Bryntum team,

I have an issue with Bryntum Scheduler filtering feature.

In horizontal mode, I have configuration to use filtering bar, and assign a listener to detect when user change the input.

At the first time scheduler is loaded, everything work normally, but when I navigate away from page, then come back, the listener stop working, even though filtering still work.

Bellow is my configuration part that involve filtering

Code: Select all

    <scheduler
      ref="scheduler"
      :resources="schedulerConfig.resources"
      :events="schedulerConfig.events"
      :start-date="schedulerConfig.startDate"
      :end-date="schedulerConfig.endDate"
      :columns="schedulerConfig.columns"
      :view-preset="schedulerConfig.viewPreset"
      :min-height="schedulerConfig.minHeight"
      :filterBarFeature="schedulerConfig.filterBarHorizontal"
    />

Code: Select all

  filterBarHorizontal: {
    filter: [{ property: 'name', value: '' }]
  },
  columns: [
    {
      text: 'Name',
      field: 'name',
      width: 130,
      filterable: {
        filterField: {
          listeners: {
            change({ value }) {
              console.log('filter changed', value);
            }
          },
          filterFn: ({ record, value }) => {
            const filterValue = value.trim();
            return record.name
              .toLowerCase()
              .includes(filterValue.toLowerCase());
          }
        }
      }
    }
  ],

I attached sample project and video to reproduce this issue. Sample project use standard vue-cli starter template.

  • Bryntum version: 3.1.9
  • Browser: Google Chrome 85.0.4183.83 (64 bit)
  • OS: MacOS Catalina (10.15.6)

Please help me with this.
Thank you

Attachments
Source.zip
(11.17 MiB) Downloaded 6 times
Screen Recording.zip
(5.27 MiB) Downloaded 5 times

User avatar
saki
Core Developer
Core Developer
Posts: 806
Joined: Thu Mar 30, 2017 9:32 am

Re: [VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by saki »

What is actually happening is the following:

  1. user navigates to Scheduler page

  2. Scheduler is created; both HTML markup and JavaScript code and variables

  3. user navigates away from page

  4. Vue router unconditionally destroys HTML markup of Scheduler

  5. user navigates back to Scheduler page

  6. new instance of Scheduler is created; HTML markup anew, some parts of JavaScript code and variables shared with step 2, some new.

The result is unpredictable and some parts of the code/markup could work and some not. Therefore, we cannot let any other code to destroy Scheduler's markup.

There are two possible ways of handling it:

  1. You do not let router to destroy the markup:

    Code: Select all

    <template>
        <div id="app">
            <demo-header title="Advanced Vue demo" />
            <keep-alive>
                <router-view/>
            </keep-alive>
      </div>
    </template>

    this is the way we use in our advanced example

  2. You intercept the routing event and you call destroy() method of the Scheduler instance before navigating away from it. This way both markup and JavaScript will be cleaned up correctly and navigating back to the scheduler page will cleanly re-create it from scratch.


User avatar
sactory
Premium Member
Premium Member
Posts: 73
Joined: Mon Jun 01, 2020 4:06 am

Re: [VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by sactory »

Thank you for your response saki.

About the two solutions you suggested:

  1. With how we structure our project <keep-alive> is not a viable option, it mess up some of our business logic so we can not use it.

  2. I tried to use beforeRouteLeave guard in route component to destroy scheduler instance, but an error show up. You can see it in the sample.

My component tree: App (root) > About (route component) > Schedule > BryntumScheduler

I have a ref to BryntumScheduler in Scheduler component, so I use event to make a referrer to the ref in About component, then use beforeRouteLeave at About component and destroy BryntumScheduler instance.

Sample code:

Code: Select all

// About.vue
<template>
  <div class="about">
    <div class="schedule">
      <Schedule @saveReferrer="saveReferrer" />
    </div>
  </div>
</template>
<script>
import Schedule from '@/components/Schedule';
export default {
  name: 'About',
  components: {
    Schedule
  },
  data: function() {
    return {
      scheduler: undefined
    };
  },
  methods: {
    saveReferrer(scheduler) {
      this.scheduler = scheduler;
    }
  },
  beforeRouteLeave(to, from, next) {
    if (this.scheduler) {
      this.scheduler.schedulerInstance.destroy();
    }
    next();
  }
};
</script>

Code: Select all

// Schedule.vue
<template>
  <div>
    <scheduler
      ref="scheduler"
      :resources="schedulerConfig.resources"
      :events="schedulerConfig.events"
      :start-date="schedulerConfig.startDate"
      :end-date="schedulerConfig.endDate"
      :columns="schedulerConfig.columns"
      :view-preset="schedulerConfig.viewPreset"
      :min-height="schedulerConfig.minHeight"
      :filterBarFeature="schedulerConfig.filterBarHorizontal"
    />
  </div>
</template>
<script>
import Scheduler from '../../bryntum/_shared/src/Scheduler.vue';
import 'bryntum-scheduler/scheduler.stockholm.css';
import schedulerConfig from './schedulerConfig';

export default {
  name: 'Schedule',
  components: {
    Scheduler
  },
  data: function() {
    return {
      schedulerConfig
    };
  },
  mounted: function() {
    this.$emit('saveReferrer', this.$refs.scheduler);
  }
};
</script>

When I navigate away it show this error message in console

Code: Select all

vue-router.esm.js?8c4f:2208 TypeError: Cannot read property 'map' of undefined
    at ColumnStore.map (scheduler.module.js?7d42:34554)
    at Scheduler.getState (scheduler.module.js?7d42:70962)
    at Scheduler.getState (scheduler.module.js?7d42:108309)
    at Scheduler.get state [as state] (scheduler.module.js?7d42:25885)
    at Object.replacer (backend.js:315)
    at encode (backend.js:3100)
    at encode (backend.js:3101)
    at encode (backend.js:3101)
    at encode (backend.js:3101)
    at encode (backend.js:3110)

What am I doing wrong here?

Attachments
Source.v2.zip
(11.17 MiB) Downloaded 6 times

User avatar
saki
Core Developer
Core Developer
Posts: 806
Joined: Thu Mar 30, 2017 9:32 am

Re: [VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by saki »

The wrapper already contains the logic to call destroy() of the instance so the following will work:

Code: Select all

  beforeRouteLeave(to, from, next) {
    if (this.scheduler) {
      this.scheduler.destroy();
    }
    next();
  }

I've tested it and then destroy and re-create works for me. However, one more workaround is needed:

Code: Select all

      filterable: {
        filterField: {
          onChange:({value}) => {
            console.log(`changed ${value}`);
          },

We're still investigating why it doesn't work with listeners because it should.


User avatar
pmiklashevich
Core Developer
Core Developer
Posts: 3024
Joined: Fri Apr 01, 2016 11:08 am

Re: [VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by pmiklashevich »

The issue with listeners is fixed in upcoming 4.0 release. You can download 4.0 beta from the Customer Zone. Thanks!

Pavel Miklashevich - Core Developer

User avatar
sactory
Premium Member
Premium Member
Posts: 73
Joined: Mon Jun 01, 2020 4:06 am

Re: [VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by sactory »

Thank you for your support.

After some trying I come up with a work around for this issue, I think the root cause can be the way configuration being initialize: configuration being exported from separate file as object then imported in Scheduler component, when we navigate away then come back it was re-used.
I changed schedulerConfig.js to export init function that return the object instead of export the object directly, then call init function in Scheduler component, this way when Scheduler is created it always use fresh configuration.
This solution solve my issue with out the need of manually call destroy method of BryntumScheduler.


User avatar
arcady
Core Developer
Core Developer
Posts: 2487
Joined: Wed Mar 20, 2013 6:57 am

Re: [VUE] Listeners of filterable column stop working when change page by vue router in horizontal mode

Post by arcady »

Ok, good to hear you're unblocked and thanks very much for sharing the solution!


Post Reply