Premium support for our pure JavaScript UI components


Post by vincenzo.menzella »

Hello everyone,

I’m using the appendChild method of TaskModel in my Angular application and I’ve noticed that this method is asynchronous. However, in Angular it doesn’t return a Promise, so I can’t use await to pause execution until it finishes.

How can I wait for appendChild to complete its operations before moving on to the next step?

Any advice or code examples would be greatly appreciated. Thank you!


Post by mats »

I cannot find any reference to it being async - where did you read this?


Post by vincenzo.menzella »

I’d like to clarify the issue with a bit more detail.

The appendChild method triggers an add event in the taskStore, but this event doesn’t fire synchronously.

ngAfterViewInit() {
        this.taskStore.on({
            add: () => console.log("taskStore event add"),
        });
    }

appendChild(): void {
    const task1 = this.taskStore?.getById("1");
    console.log("before appendChild");
    task1?.appendChild(
        new TaskModel({ id: "test", name: "Test", duration: 1 })
    );
    console.log("after appendChild");
    setTimeout(() => console.log("after setTimeout 500ms"), 500);
}

Right now, the flow of operations looks like this:
1) before appendChild.
2) after appendChild.
3) taskStore event add.

What I’d like to achieve is:
1) before appendChild.
2) taskStore event add.
3) after appendChild.

In other words, I need to wait until the add event has completed before continuing.

I’ve attached a small sample project that reproduces this behavior.
Does anyone know how I can properly wait for the add event to finish?

Thanks in advance!

Attachments
gantt-angular-inline-data_appendChild.zip
(137.88 KiB) Downloaded 7 times

Post by tasnim »

I don't see that in the codebase; it is async. Could you please let us know what issues you are facing that you'd need to wait there? We might be able to help you in some other way, knowing your use case!

Best regards,
Tasnim

How to ask for help? Please read our Support Policy


Post by vincenzo.menzella »

Let me explain my specific use case in more detail, because I think that’s where the confusion is:
In my taskStore.onAdd handler, I call event.records.forEach(task => task.clearChanges());
I do this because any new tasks created must be immediately saved to the backend.
After that initial save, any further edits to the same task should go into changes.modified rather than changes.added.

My flow is:
1) task.appendChild(newTask)
2) taskStore.onAdd(event => event.records.forEach(task => task.clearChanges())) – clears the added flag on the new task
3) newTask.customField = 'new Value'
4) Expected: taskStore.changes.modified contains newTask (because we just changed customField)

What actually happens:
1) task.appendChild(newTask)
2) newTask.customField = 'new Value'
3) taskStore.onAdd(...) finally fires, clearing all pending changes (including the customField change)
4) taskStore.changes.modified is empty

This is the code:

ngAfterViewInit() {
        this.taskStore.on({
            add: (event) => event.records.forEach(task => task.clearChanges()),
        });
    }

test(): void {
    const newTask = new TaskModel({ id: '2', name: 'new Task', duration: 1, customField: 'value' });
    const taskParent = this.taskStore?.getById('1');
    taskParent?.appendChild(newTask);
    newTask.customField = 'new Value';
    console.log('TaskStore changes modified:', this.taskStore.changes.modified); // empty
}

In other words, my onAdd handler doesn’t run immediately after appendChild, so my custom-field edit happens before the added-task changes are cleared.

What I need is a way to await until the add event has fully fired (and clearChanges() has run) before I make any further edits.


Post by ghulam.ghous »

Hey,

I understand your use-case and unfortunately I am not able to find any api that can suffice your need. I am curious that why are you not syncing the changes with the backend instead of clearing them? And if you clear the added records, and the changes are let's say tracked under modified, isn't it gonna break backend? Because no such record is going to be existed on backend for modification.

But as we have already mentioned that appendChild is not async. But one thing you can do is use addAsync instead of appendChild. But here the issue comes with clearing of the changes, as that method is not async as well.

    tbar : {
        items : {
            btn : {
                type : 'button',
                text : 'Button',
                async onClick(e){
                    const a = await gantt.taskStore.addAsync({ parentId: 1, name: 'new Task', duration: 1, customField: 'value' });
                    
                    a[0].customField = 'new Value';
                    console.log('TaskStore changes modified:', gantt.taskStore.changes);
                }
            }
        } 
    }

So I would say the best solution is to sync the changes with the backend and then update the fields.


Post by vincenzo.menzella »

The reason I’m clearing the added changes immediately is that new tasks are already synced to the backend before I ever call appendChild. In other words, the creation flow looks like this:
1) Create child task on backend via a REST API call.
2) Backend responds with success (and returns the new task ID, etc.).
3) task.appendChild(newTask) – I attach that server-created task into the Gantt’s taskStore.
4) In my taskStore.onAdd handler, I immediately call: taskStore.onAdd(event => event.records.forEach(task => task.clearChanges())).

After appendChild, I need to update the value of newTask.customField immediately, and that change must put newTask into changes.modified.

Later on, when the user clicks my custom “Save” button, I send only the tasks in taskStore.changes.modified to the backend.


Post by alex.l »

Hi,

This is not typical flow for such operation, so we do not have out of box solution. Usually and more easy, to add task using UI/API into our stores, which triggers 'add' event, that you can use to sync with backend. After it synced, you can commit changes (mark them saved) and do all other operations.
In your case, addAsync might be that you're looking for, as well as adding tasks with real id that will mark task as modified, not added (this is the difference via those 2 - added array required id to be set on backend).
I would say something like:
1) save on BE, get ids
2) addAsync
3) commit changes in store
4) apply required changes
5) get tasks as modified with required changes

All the best,
Alex Lazarev

How to ask for help? Please read our Support Policy

We do not write the code in bounds of forum support. If you need help with development, contact us via bryntum.com/services


Post Reply