diff --git a/src/htmx.js b/src/htmx.js index 709f91ac..3afe494c 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -2277,7 +2277,7 @@ var htmx = (function() { * @param {HtmxTriggerSpecification[]} triggerSpecs */ function boostElement(elt, nodeData, triggerSpecs) { - if ((elt instanceof HTMLAnchorElement && isLocalLink(elt) && (elt.target === '' || elt.target === '_self')) || elt.tagName === 'FORM') { + if ((elt instanceof HTMLAnchorElement && isLocalLink(elt) && (elt.target === '' || elt.target === '_self')) || (elt.tagName === 'FORM' && String(getRawAttribute(elt, 'method')).toLowerCase() !== 'dialog')) { nodeData.boosted = true let verb, path if (elt.tagName === 'A') { @@ -3925,7 +3925,7 @@ var htmx = (function() { if (obj.hasOwnProperty(key)) { if (typeof obj[key].forEach === 'function') { obj[key].forEach(function(v) { formData.append(key, v) }) - } else if (typeof obj[key] === 'object') { + } else if (typeof obj[key] === 'object' && !(obj[key] instanceof Blob)) { formData.append(key, JSON.stringify(obj[key])) } else { formData.append(key, obj[key]) diff --git a/test/attributes/hx-boost.js b/test/attributes/hx-boost.js index d8156778..e6562e48 100644 --- a/test/attributes/hx-boost.js +++ b/test/attributes/hx-boost.js @@ -71,6 +71,14 @@ describe('hx-boost attribute', function() { div.innerHTML.should.equal('Boosted') }) + it('does not boost forms with method="dialog"', function() { + make('
') + var form = byId('f1') + + var internalData = htmx._('getInternalData')(form) + should.equal(undefined, internalData.boosted) + }) + it('handles basic anchor properly w/ data-* prefix', function() { this.server.respondWith('GET', '/test', 'Boosted') var div = make('') diff --git a/test/core/parameters.js b/test/core/parameters.js index f1df2d7e..ecf71a59 100644 --- a/test/core/parameters.js +++ b/test/core/parameters.js @@ -312,4 +312,56 @@ describe('Core htmx Parameter Handling', function() { this.server.respond() form.innerHTML.should.equal('Clicked!') }) + + it('file is correctly uploaded with file input', function() { + this.server.respondWith('POST', '/test', function(xhr) { + should.equal(xhr.requestHeaders['Content-Type'], undefined) + + const file = xhr.requestBody.get('file') + file.should.instanceOf(File) + file.name.should.equal('test.txt') + + xhr.respond(200, {}, 'OK') + }) + + const form = make('') + const input = form.querySelector('input') + const file = new File(['Test'], 'test.txt', { type: 'text/plain' }) + const dataTransfer = new DataTransfer() + dataTransfer.items.add(file) + input.files = dataTransfer.files + + const result = make('') + + form.querySelector('button').click() + this.server.respond() + result.innerHTML.should.equal('OK') + }) + + it('file is correctly uploaded with htmx.ajax', function() { + this.server.respondWith('POST', '/test', function(xhr) { + should.equal(xhr.requestHeaders['Content-Type'], undefined) + + const file = xhr.requestBody.get('file') + file.should.instanceOf(File) + file.name.should.equal('test.txt') + + xhr.respond(200, {}, 'OK') + }) + + const div = make('') + + htmx.ajax('POST', '/test', { + source: div, + values: { + file: new File(['Test'], 'test.txt', { type: 'text/plain' }) + } + }) + + this.server.respond() + div.innerHTML.should.equal('OK') + }) })