diff --git a/src/json-enc/json-enc.js b/src/json-enc/json-enc.js index 3991892..8f03c96 100644 --- a/src/json-enc/json-enc.js +++ b/src/json-enc/json-enc.js @@ -27,7 +27,11 @@ }) const vals = api.getExpressionVars(elt) - Object.keys(object).forEach(function(key) { + // A hx-vals/hx-vars key whose value serializes to nothing in FormData (e.g. an + // empty array) has no entry in `object` yet, so the key set to restore over must + // be the union of both, not just what FormData produced. + const keys = new Set(Object.keys(object).concat(Object.keys(vals))) + keys.forEach(function(key) { // FormData encodes values as strings, restore hx-vals/hx-vars with their initial types object[key] = Object.hasOwn(vals, key) ? vals[key] : object[key] }) diff --git a/src/json-enc/test/ext/json-enc.js b/src/json-enc/test/ext/json-enc.js index 88e7014..d8bd052 100644 --- a/src/json-enc/test/ext/json-enc.js +++ b/src/json-enc/test/ext/json-enc.js @@ -182,6 +182,25 @@ describe('json-enc extension', function() { form.innerHTML.should.equal('OK') }) + it('keeps hx-vals keys whose value serializes to nothing in FormData', function() { + var values = {} + this.server.respondWith('POST', '/test', function(xhr) { + values = JSON.parse(xhr.requestBody) + xhr.respond(200, {}, 'clicked') + }) + + make(`
`) + var btn = byId('btn') + btn.click() + this.server.respond() + + values.should.have.keys('firstLevel', 'secondLevel') + chai.assert.deepEqual(values.firstLevel, []) + chai.assert.deepEqual(values.secondLevel, { values: [] }) + }) + it('handles multiple select', function() { this.server.respondWith('POST', '/test', function(xhr) { var values = JSON.parse(xhr.requestBody)