Skip to content

Commit ea02238

Browse files
committed
Prevent action events from getting attached to document more than once. Don't exclude element from setting model value when there is a callMethod action in the action queue.
1 parent 53c97ec commit ea02238

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

django_unicorn/static/js/unicorn.js

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ const Unicorn = (() => {
355355
this.actionQueue = [];
356356
this.currentActionQueue = null;
357357
this.actionEvents = {};
358+
this.attachedEventTypes = [];
358359

359360
this.init();
360361
this.refreshEventListeners();
@@ -410,11 +411,13 @@ const Unicorn = (() => {
410411
const action = { type: "syncInput", payload: { name: element.model.name, value: element.getValue() } };
411412
this.actionQueue.push(action);
412413

413-
this.sendMessage(element.model.debounceTime, (err) => {
414+
this.sendMessage(element.model.debounceTime, (excludeElement, err) => {
414415
if (err) {
415416
console.error(err);
416-
} else {
417+
} else if (excludeElement) {
417418
this.setModelValues(element);
419+
} else {
420+
this.setModelValues();
418421
}
419422
});
420423
});
@@ -447,7 +450,11 @@ const Unicorn = (() => {
447450
this.actionEvents[element.action.eventType].push(element);
448451
} else {
449452
this.actionEvents[element.action.eventType] = [element];
450-
this.addActionEventListener(element.action.eventType);
453+
454+
if (this.attachedEventTypes.filter((et) => et === element.action.eventType).length === 0) {
455+
this.attachedEventTypes.push(element.action.eventType);
456+
this.addActionEventListener(element.action.eventType);
457+
}
451458
}
452459
}
453460
}
@@ -461,7 +468,7 @@ const Unicorn = (() => {
461468
const action = { type: "callMethod", payload: { name: methodName, params: [] } };
462469
this.actionQueue.push(action);
463470

464-
this.sendMessage(-1, (err) => {
471+
this.sendMessage(-1, (_, err) => {
465472
if (err && typeof errCallback === "function") {
466473
errCallback(err);
467474
} else if (err) {
@@ -684,19 +691,31 @@ const Unicorn = (() => {
684691
});
685692
});
686693

694+
// Check if the current actionQueue contains a callMethod. Prevents excluding
695+
// an element from getting a value set because calling a component function can
696+
// potentially have side effects which have to be reflected on the current element.
697+
let hasCallMethod = false;
698+
699+
_component.currentActionQueue.forEach((action) => {
700+
if (action.type === "callMethod") {
701+
hasCallMethod = true;
702+
}
703+
});
704+
687705
// Clear the current action queue
688706
_component.currentActionQueue = null;
689707

690708
if (callback && typeof callback === "function") {
691-
callback();
709+
callback(!hasCallMethod, null);
692710
}
693711
})
694712
.catch((err) => {
713+
// Make sure to clear the current queues in case of an error
695714
_component.actionQueue = [];
696715
_component.currentActionQueue = null;
697716

698717
if (callback && typeof callback === "function") {
699-
callback(err);
718+
callback(null, err);
700719
}
701720
});
702721
}

0 commit comments

Comments
 (0)