How to partially refresh gantt chart ?

How to make the TaskBar change immediately when updating TaskStatus?

Code  snippet

const queryTaskbarInfo = (args: any) => {
      // Significant Delay: Salmon red
      // Minor Delay: Gold GoldenRod
      // OnTime: LimeGreen Green
      // Compledted: LightGray DarkGray
      switch (args.data.taskData.TaskStatus) {
            case "OnTime":
                  args.taskbarBgColor = "LimeGreen";
                  args.progressBarBgColor = "Green";
                  break;
            case "Minor Delay":
                  args.taskbarBgColor = "Gold";
                  args.progressBarBgColor = "GoldenRod";
                  break;
            case "Significant Delay":
                  args.taskbarBgColor = "Salmon";
                  args.progressBarBgColor = "Red";
                  break;
            case "Completed":
                  args.taskbarBgColor = "LightGray";
                  args.taskbarBorderColor = "DarkGray";
                  args.progressBarBgColor = "DarkGray";
      }
};

const rowDataBound = (args: any) => {
      switch (args.data.taskData.TaskStatus) {
            case "OnTime":
                  args.row.style.backgroundColor = "#d4ecd5";
                  break;
            case "Minor Delay":
                  args.row.style.backgroundColor = "#fef0cd";
                  break;
            case "Significant Delay":
                  args.row.style.backgroundColor = "#ffd1ce";
                  break;
            case "Completed":
                  args.row.style.backgroundColor = "#d9e0e3";
                  break;
      }
};


8 Replies

AG Ajithkumar Gopalakrishnan Syncfusion Team October 30, 2024 03:13 PM UTC

Hi Wyatt,

Greetings from Syncfusion Support,

We have reviewed the shared code snippet and query on our end. In our sample, we are using the queryTaskbarInfo and rowDataBound events. The ‘TaskStatus’ custom column value dynamically changes for any record, automatically triggering the rowDataBound and queryTaskbarInfo events. Based on the shared code snippet, colors are updating properly on our end. Please refer to the attached code snippet and sample.

<ejs-gantt ref='gantt' id="GanttContainer"

           :dataSource="data"

           ...

           :queryTaskbarInfo="queryTaskbarInfo"

           :rowDataBound="rowDataBound">

</ejs-gantt>

queryTaskbarInfo(args)

{

    switch (args.data.taskData.TaskStatus)

    {

        case "OnTime":

            args.taskbarBgColor = "LimeGreen";

            args.progressBarBgColor = "Green";

            break;

        case "MinorDelay":

            args.taskbarBgColor = "Gold";

            args.progressBarBgColor = "GoldenRod";

            break;

        case "SignificantDelay":

            args.taskbarBgColor = "Salmon";

            args.progressBarBgColor = "Red";

            break;

        case "Completed":

            args.taskbarBgColor = "LightGray";

            args.taskbarBorderColor = "DarkGray";

            args.progressBarBgColor = "DarkGray";

    }

},

rowDataBound(args)

{

    switch (args.data.taskData.TaskStatus)

    {

        case "OnTime":

            args.row.style.backgroundColor = "#d4ecd5";

            break;

        case "MinorDelay":

            args.row.style.backgroundColor = "#fef0cd";

            break;

        case "SignificantDelay":

            args.row.style.backgroundColor = "#ffd1ce";

            break;

        case "Completed":

            args.row.style.backgroundColor = "#d9e0e3";

            break;

    }

}


You can find a working example on StackBlitz.

Note: Whenever you need a full refresh of the Gantt chart, please use our public refresh method. For a partial refresh, kindly provide more details regarding your specific requirements, and we will share relevant details on our end.

For more information, you may refer to the following link:

https://ej2.syncfusion.com/vue/documentation/gantt/taskbar?cs-save-lang=1&cs-lang=html#conditional-formatting

Vue Gantt API component - Syncfusion

If you have any further questions or need additional assistance, please let me know!

Regards,
Ajithkumar G



WL Wyatt Li November 1, 2024 01:51 AM UTC

For example, when I add a new task, in the onActionBegin method, I first execute the SQL write operation (using await to wait) and then return the successfully written data to update the Gantt chart data through the syncfusionGantt.value.ej2Instances.updateRecordByID method. However, the queryTaskbarInfo and rowDataBound methods are not triggered after the SQL write completes, and the Gantt chart data is not updated.


const onActionBegin = async (args: any) => {
      switch (args.requestType) {
            case "beforeAdd":
                  try {
                        let res = await PCSService.ProjectGanttTask_Insert(ganttTaskUpdateObj(args));

                        await PCSService.ProjectGantt_Update(ganttTaskBatchUpdateObj(args));

                        ganttData.value.push(res);

                        const data = syncfusionGantt.value.ej2Instances.getRecordByID(res.GanttTaskID);

                        data.taskData.Project_ID = res.Project_ID;

                        data.taskData.ProjectTask_ID = res.ProjectTask_ID;

                        syncfusionGantt.value.ej2Instances.updateRecordByID(res.GanttTaskID, res);

                        await reorderGanttIndex();

                        toast.add({
                              severity: "success",
                              summary: successLocale.value,
                              detail: addCompletedLocale.value,
                              life: 5000
                        });
                  } catch (error) {
                        toast.add({
                              severity: "error",
                              summary: failureLocale.value,
                              detail: addFailedLocale.value,
                              life: 5000
                        });

                        args.cancel = true;

                        await projectGet();
                  }

                  break;

            case "beforeSave":
                  try {
                        await PCSService.ProjectGantt_Update(ganttTaskBatchUpdateObj(args));

                        toast.add({
                              severity: "success",
                              summary: successLocale.value,
                              detail: updateCompletedLocale.value,
                              life: 5000
                        });
                  } catch (error) {
                        toast.add({
                              severity: "error",
                              summary: failureLocale.value,
                              detail: updateFailedLocale.value,
                              life: 5000
                        });

                        args.cancel = true;

                        await projectGet();
                  }

                  break;
            case "beforeDelete":
                  try {
                        if (args.data) {
                              for (let i = 0; i < args.data.length; i++) {
                                    await PCSService.ProjectGanttTask_Delete(args.data[i].taskData.ProjectTask_ID);
                              }

                              toast.add({
                                    severity: "success",
                                    summary: successLocale.value,
                                    detail: deleteCompletedLocale.value,
                                    life: 5000
                              });
                        }
                  } catch (error) {
                        toast.add({
                              severity: "error",
                              summary: failureLocale.value,
                              detail: deleteFailedLocale.value,
                              life: 5000
                        });

                        args.cancel = true;

                        await projectGet();
                  }

                  break;
            default:
                  //console.log(args.requestType);
                  //console.log(args);
                  break;
      }
};


AG Ajithkumar Gopalakrishnan Syncfusion Team November 4, 2024 11:53 AM UTC

Hi Wyatt,

Before proceeding, we need clarification on your code. When adding a record with the beforeAdd request type, why is updateRecordByID triggered in the actionBegin event? Since the record has not yet been added, triggering updateRecordByID at this stage may not be appropriate. If the goal is to update the record after the addition is complete, please use updateRecordByID in the actionComplete event instead.

Regards,
Ajithkumar G



WL Wyatt Li November 5, 2024 01:20 AM UTC

Hi Ajithkumar,

Before updating the Gantt chart, we are writing data to the SQL database and retrieving the record ID to update the Gantt chart using the updateRecordByID method. If the write operation fails, we can use cancel to stop the update. However, if the SQL write fails after the actionComplete event, the only option is to refresh the Gantt chart by reloading the data.

Is there a better approach to handle this? Any suggestions would be greatly appreciated. Thank you!

Best regards,
Wyatt



AG Ajithkumar Gopalakrishnan Syncfusion Team November 5, 2024 02:14 PM UTC

Hi Wyatt,


Before proceeding, we request you to share more information to achieve your requirement. Kindly share the details below.

  • If any field value is changed on the server side, could you specify which one(s)?
  • Server-side changes are automatically reflected on the client side without the need for a manual refresh, could you clarify in which situations a client-side refresh is still required?
  • We noticed the updateRecordByID method is being used. Could you provide more context on its intended purpose in your implementation?
  • If updateRecordByID is causing actionBegin and actionComplete events to trigger recursively, have you implemented any restrictions to prevent this in your code?
  • If a record fails to update on the server side, setting args.cancel to false on the client side should revert the add/edit action.  Could you provide details on the type of exception or error you are encountering when calling this method?


Once we receive this information, we will be better equipped to identify the root cause of the issue and provide you with the necessary assistance.

Regards,

Ajithkumar G



WL Wyatt Li November 6, 2024 02:03 AM UTC

Hi Ajithkumar,

  1. In the database, aside from GanttTaskID, there is also DataID (Primary Key in the table). When adding a task, it’s necessary to write the obtained ID back to the Gantt chart source, which is why updateRecordByID is called for the update. Without calling this method and merely writing the data into the source array, the dataID won’t be found during subsequent modifications.

  2. After triggering the onActionCompleted event, is it possible to cancel the previous operation?

I haven't used Syncfusion's provided CRUD API but instead am triggering onActionBegin and mapping each args.requestType to different database write operations (CRUD) based on conditions like beforeAdd and beforeSave. This also helps isolate recursive calls.

Additionally, I need to know the execution order of onActionBegin, onActionCompleted, queryTaskbarInfo, and rowDataBound. I noticed an odd behavior: when calling await in onActionBegin, the onActionCompleted event finishes first and then returns to process the awaited function. Why does this happen?





WL Wyatt Li November 15, 2024 01:50 AM UTC

Hello, Excuse me ?



AG Ajithkumar Gopalakrishnan Syncfusion Team November 15, 2024 12:11 PM UTC

Hi Wyatt,

Sorry for the inconvenience caused.

Query 1- In the database, aside from GanttTaskID, there is also DataID (Primary Key in the table). When adding a task, it’s necessary to write the obtained ID back to the Gantt chart source, which is why updateRecordByID is called for the update. Without calling this method and merely writing the data into the source array, the dataID won’t be found during subsequent modifications.

To achieve your requirement, we suggest using the actionBegin event in the Gantt chart. Based on your query, using updateRecordByID to update the record is unnecessary. Instead, the issue can be resolved by manually modifying the taskData of the custom column in the actionBegin event during the add request type. The DataID can then be updated in the backend database as well. Additionally, you can maintain the taskData whenever an action is triggered from the Gantt chart. We have attached the relevant code snippet and a sample for reference:

<ejs-gantt ref='gantt' id="GanttContainer"

          

           :actionBegin="actionBegin"

           :columns="columns"

           >

           ..

</ejs-gantt>

columns: [

   { field: 'taskId',  },

       ...

   { field: 'dataID', type: 'number' },

],

actionBegin(args)

{

    if (args.requestType == "beforeAdd")

    {

        args.data.dataID = args.data.taskId;

        args.data.taskData.dataID = args.data.taskId;

    }

},


Client sample: 8uez3c (forked) - StackBlitz

Server sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/load-on-demand-1365213382.zip

Query 2-
After triggering the onActionCompleted event, is it possible to cancel the previous operation?

We need to clarify the behavior of the Gantt chart. When an action is triggered, it begins with the actionBegin event, and after the action completes, the actionComplete event is triggered. Since the operation is already complete when actionComplete is fired, it is not possible to cancel the action at this stage. If you need to cancel an action, you must use the actionBegin event.

Query 3- I noticed an odd behavior: when calling await in onActionBegin, the onActionCompleted event finishes first and then returns to process the awaited function. Why does this happen?

Yes, this is the expected behavior of JavaScript's event loop. When await is used, the execution of the actionBegin function pauses at that point, allowing other tasks in the event loop to proceed. While the await waits for the promise to resolve, the Gantt chart’s internal logic continues, triggering the actionComplete event as soon as its operation finishes, even if the awaited logic in actionBegin has not yet completed.

In the Gantt chart, the actionBegin event occurs before the operation, and the actionComplete event occurs after the operation. If await is used in actionBegin, the Gantt chart's internal event lifecycle is not blocked by the promise's resolution. Consequently, the actionComplete event is triggered as soon as the operation finishes, irrespective of whether the awaited function in actionBegin has finished processing.

Regards,
Ajithkumar G


Loader.
Up arrow icon