jQuery UI Widgets › Forums › Scheduler › In Vue, what pattern works best to sync jqxScheduler edits back to reactive stor

This topic contains 1 reply, has 2 voices, and was last updated by  admin 2 weeks, 2 days ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author

  • sande
    Participant

    Hi everyone, I am working on an internal admin dashboard with Scheduler.

    I am currently trying to solve this: In Vue, what pattern works best to sync jqxScheduler edits back to reactive store without causing duplicate update loops?

    So far, I can reproduce it consistently in a small demo, but the component updates only after a manual refresh.

    Is there an official pattern for this scenario?


    admin
    Keymaster

    Hi,

    To sync jqxScheduler edits back to a reactive store (like Pinia or a Vue reactive object) without triggering duplicate update loops or getting stuck requiring a manual refresh, you need to implement a one-way data flow with event-driven synchronization.

    You can try this:

    <script setup>
    import { ref, onMounted, toRaw } from 'vue';
    import JqxScheduler from 'jqwidgets-scripts/jqwidgets-vue3/vue_jqxscheduler.vue';
    import { useAppointmentStore } from '@/stores/appointmentStore'; // Example Pinia Store
    
    const store = useAppointmentStore();
    const schedulerRef = ref(null);
    
    // Loop guard flag
    let isUpdatingStore = false;
    
    // 1. Map store data to the jqx DataAdapter schema
    const source = {
      dataType: "array",
      dataFields: [
        { name: 'id', type: 'string' },
        { name: 'description', type: 'string' },
        { name: 'location', type: 'string' },
        { name: 'subject', type: 'string' },
        { name: 'start', type: 'date' },
        { name: 'end', type: 'date' }
      ],
      id: 'id',
      // Extract un-observed raw data to prevent jqx framework collisions
      localData: toRaw(store.appointments) 
    };
    
    const dataAdapter = new $.jqx.dataAdapter(source);
    
    // 2. Handle component edits and push to store
    const handleAppointmentChange = (event) => {
      if (isUpdatingStore) return; // Prevent infinite loops if store triggers a redraw
    
      const appointment = event.args.appointment;
      
      // Guard the execution block
      isUpdatingStore = true;
      
      store.updateAppointment({
        id: appointment.id,
        subject: appointment.subject,
        start: appointment.originalData.start, // Use raw dates from jqx payload
        end: appointment.originalData.end,
        description: appointment.description
      });
    
      isUpdatingStore = false;
    };
    
    // 3. Reacting to global store changes from outside the scheduler
    store.$subscribe((mutation, state) => {
      // If the update originated from the scheduler itself, do nothing
      if (isUpdatingStore || !schedulerRef.value) return;
    
      // Otherwise, safely refresh the widget with the fresh dataset
      source.localData = toRaw(state.appointments);
      const updatedAdapter = new $.jqx.dataAdapter(source);
      
      // Re-assigning the source forces jqxScheduler to redraw seamlessly
      schedulerRef.value.source(updatedAdapter); 
    });
    </script>
    
    <template>
      <JqxScheduler
        ref="schedulerRef"
        :source="dataAdapter"
        @appointmentChange="handleAppointmentChange"
        @appointmentAdd="handleAppointmentChange" 
      />
    </template>

    Best regards,
    Peter

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.