Skip to content

Commit 521b573

Browse files
committed
Revert loading and dirty elements when there is a 304 or 500 from the server.
1 parent 7758244 commit 521b573

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

django_unicorn/static/unicorn/js/element.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,10 @@ export class Element {
195195

196196
/**
197197
* Handle loading for the element.
198+
* @param {bool} revert Whether or not the revert the loading class.
198199
*/
199-
handleLoading() {
200-
this.handleInterfacer("loading");
200+
handleLoading(revert) {
201+
this.handleInterfacer("loading", revert);
201202
}
202203

203204
/**

django_unicorn/static/unicorn/js/messageSender.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ export function send(component, callback) {
5050
return response.json();
5151
}
5252

53+
// Revert targeted loading elements, loading states,
54+
// and dirty states when the response is not ok (includes 304)
55+
component.loadingEls.forEach((loadingElement) => {
56+
if (loadingElement.loading.hide) {
57+
loadingElement.show();
58+
} else if (loadingElement.loading.show) {
59+
loadingElement.hide();
60+
}
61+
62+
loadingElement.handleLoading(true);
63+
loadingElement.handleDirty(true);
64+
});
65+
5366
// HTTP status code of 304 is `Not Modified`. This null gets caught in the next promise
5467
// and stops any more processing.
5568
if (response.status === 304) {

tests/js/element/action.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import test from "ava";
2+
import fetchMock from "fetch-mock";
3+
import { send } from "../../../django_unicorn/static/unicorn/js/messageSender.js";
24
import { getComponent, getElement } from "../utils.js";
35

46
test("click", (t) => {
@@ -313,6 +315,59 @@ test("event action loading class", (t) => {
313315
t.is(el.classList[0], "loading");
314316
});
315317

318+
test.cb("event action loading attr 500 reverts", (t) => {
319+
const html = `
320+
<div unicorn:id="5jypjiyb" unicorn:name="text-inputs" unicorn:checksum="GXzew3Km">
321+
<button unicorn:click='test()' u:loading.attr="disabled"></button>
322+
</div>`;
323+
const component = getComponent(html);
324+
325+
t.is(component.attachedEventTypes.length, 1);
326+
t.is(component.actionEvents.click.length, 1);
327+
328+
const { el } = component.actionEvents.click[0].element;
329+
t.true(typeof el.attributes.disabled === "undefined");
330+
331+
el.click();
332+
t.false(typeof el.attributes.disabled === "undefined");
333+
334+
// mock the fetch
335+
global.fetch = fetchMock.sandbox().mock().post("/test/text-inputs", 500);
336+
337+
send(component, (_, __, err) => {
338+
t.true(typeof el.attributes.disabled === "undefined");
339+
fetchMock.reset();
340+
t.end();
341+
});
342+
});
343+
344+
test.cb("event action loading class 500 reverts", (t) => {
345+
const html = `
346+
<div unicorn:id="5jypjiyb" unicorn:name="text-inputs" unicorn:checksum="GXzew3Km">
347+
<button unicorn:click='test()' u:loading.class="loading-class"></button>
348+
</div>`;
349+
const component = getComponent(html);
350+
351+
t.is(component.attachedEventTypes.length, 1);
352+
t.is(component.actionEvents.click.length, 1);
353+
354+
const { el } = component.actionEvents.click[0].element;
355+
t.is(el.classList.length, 0);
356+
357+
el.click();
358+
t.is(el.classList.length, 1);
359+
t.is(el.classList[0], "loading-class");
360+
361+
// mock the fetch
362+
global.fetch = fetchMock.sandbox().mock().post("/test/text-inputs", 500);
363+
364+
send(component, (_, __, err) => {
365+
t.is(el.classList.length, 0);
366+
fetchMock.reset();
367+
t.end();
368+
});
369+
});
370+
316371
test("event action loading remove class", (t) => {
317372
const html = `
318373
<div unicorn:id="5jypjiyb" unicorn:name="text-inputs" unicorn:checksum="GXzew3Km">

0 commit comments

Comments
 (0)