Skip to content

Commit c6a0c19

Browse files
committed
Improve pushUrl and hx-location url handling
1 parent fb7761e commit c6a0c19

File tree

5 files changed

+87
-10
lines changed

5 files changed

+87
-10
lines changed

src/htmx.js

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4669,7 +4669,7 @@ var htmx = (function() {
46694669
const requestPath = responseInfo.pathInfo.finalRequestPath
46704670
const responsePath = responseInfo.pathInfo.responsePath
46714671

4672-
const pushUrl = getClosestAttributeValue(elt, 'hx-push-url')
4672+
const pushUrl = getClosestAttributeValue(elt, 'hx-push-url') || responseInfo.etc.pushUrl
46734673
const replaceUrl = getClosestAttributeValue(elt, 'hx-replace-url')
46744674
const elementIsBoosted = getInternalData(elt).boosted
46754675

@@ -4707,11 +4707,6 @@ var htmx = (function() {
47074707
type: saveType,
47084708
path
47094709
}
4710-
} else if (responseInfo.etc.pushUrl) {
4711-
return {
4712-
type: 'push',
4713-
path: responsePath || requestPath
4714-
}
47154710
} else {
47164711
return {}
47174712
}
@@ -4796,14 +4791,14 @@ var htmx = (function() {
47964791
if (hasHeader(xhr, /HX-Location:/i)) {
47974792
let redirectPath = xhr.getResponseHeader('HX-Location')
47984793
/** @type {HtmxAjaxHelperContext&{path?:string}} */
4799-
var redirectSwapSpec = { pushUrl: true }
4794+
var redirectSwapSpec = {}
48004795
if (redirectPath.indexOf('{') === 0) {
48014796
redirectSwapSpec = parseJSON(redirectPath)
48024797
// what's the best way to throw an error if the user didn't include this
48034798
redirectPath = redirectSwapSpec.path
48044799
delete redirectSwapSpec.path
4805-
redirectSwapSpec.pushUrl = true
48064800
}
4801+
redirectSwapSpec.pushUrl = redirectSwapSpec.pushUrl || 'true'
48074802
ajaxHelper('get', redirectPath, redirectSwapSpec)
48084803
return
48094804
}
@@ -5220,7 +5215,7 @@ var htmx = (function() {
52205215
* @property {Object|FormData} [values]
52215216
* @property {Record<string,string>} [headers]
52225217
* @property {string} [select]
5223-
* @property {boolean} [pushUrl]
5218+
* @property {string} [pushUrl]
52245219
*/
52255220

52265221
/**
@@ -5267,7 +5262,7 @@ var htmx = (function() {
52675262
* @property {Object|FormData} [values]
52685263
* @property {boolean} [credentials]
52695264
* @property {number} [timeout]
5270-
* @property {boolean} [pushUrl]
5265+
* @property {string} [pushUrl]
52715266
*/
52725267

52735268
/**

test/core/api.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,4 +656,34 @@ describe('Core htmx API test', function() {
656656
var div = make('<div>textNode</div>')
657657
htmx.process(div.firstChild)
658658
})
659+
660+
it('ajax api pushUrl should push an element into the cache when true', function() {
661+
this.server.respondWith('POST', '/test123', 'Clicked!')
662+
663+
var div = make("<div id='d1'></div>")
664+
htmx.ajax('POST', '/test123', {
665+
target: '#d1',
666+
swap: 'innerHTML',
667+
pushUrl: 'true'
668+
})
669+
this.server.respond()
670+
div.innerHTML.should.equal('Clicked!')
671+
var path = sessionStorage.getItem('htmx-current-path-for-history')
672+
path.should.equal('/test123')
673+
})
674+
675+
it('ajax api pushUrl should push an element into the cache when string', function() {
676+
this.server.respondWith('POST', '/test', 'Clicked!')
677+
678+
var div = make("<div id='d1'></div>")
679+
htmx.ajax('POST', '/test', {
680+
target: '#d1',
681+
swap: 'innerHTML',
682+
pushUrl: '/abc123'
683+
})
684+
this.server.respond()
685+
div.innerHTML.should.equal('Clicked!')
686+
var path = sessionStorage.getItem('htmx-current-path-for-history')
687+
path.should.equal('/abc123')
688+
})
659689
})

test/core/headers.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,56 @@ describe('Core htmx AJAX headers', function() {
410410
}, 30)
411411
})
412412

413+
it('should push new Url on HX-Location', function(done) {
414+
sessionStorage.removeItem('htmx-current-path-for-history')
415+
this.server.respondWith('GET', '/test', [200, { 'HX-Location': '{"path":"/test2", "target":"#work-area"}' }, ''])
416+
this.server.respondWith('GET', '/test2', [200, {}, '<div>Yay! Welcome</div>'])
417+
var div = make('<div id="testdiv" hx-trigger="click" hx-get="/test"></div>')
418+
div.click()
419+
this.server.respond()
420+
this.server.respond()
421+
setTimeout(function() {
422+
getWorkArea().innerHTML.should.equal('<div>Yay! Welcome</div>')
423+
var path = sessionStorage.getItem('htmx-current-path-for-history')
424+
path.should.equal('/test2')
425+
done()
426+
}, 30)
427+
})
428+
429+
it('should not push new Url on HX-Location if pushUrl false', function(done) {
430+
sessionStorage.setItem('htmx-current-path-for-history', '/old')
431+
this.server.respondWith('GET', '/test', [200, { 'HX-Location': '{"pushUrl":"false", "path":"/test2", "target":"#work-area"}' }, ''])
432+
this.server.respondWith('GET', '/test2', [200, {}, '<div>Yay! Welcome</div>'])
433+
var div = make('<div id="testdiv" hx-trigger="click" hx-get="/test"></div>')
434+
div.click()
435+
this.server.respond()
436+
this.server.respond()
437+
setTimeout(function() {
438+
getWorkArea().innerHTML.should.equal('<div>Yay! Welcome</div>')
439+
var path = sessionStorage.getItem('htmx-current-path-for-history')
440+
path.should.equal('/old')
441+
done()
442+
}, 30)
443+
})
444+
445+
it('should push different Url on HX-Location if pushUrl is string', function(done) {
446+
sessionStorage.removeItem('htmx-current-path-for-history')
447+
var HTMX_HISTORY_CACHE_NAME = 'htmx-history-cache'
448+
sessionStorage.removeItem(HTMX_HISTORY_CACHE_NAME)
449+
this.server.respondWith('GET', '/test', [200, { 'HX-Location': '{"pushUrl":"/abc123", "path":"/test2", "target":"#work-area"}' }, ''])
450+
this.server.respondWith('GET', '/test2', [200, {}, '<div>Yay! Welcome</div>'])
451+
var div = make('<div id="testdiv" hx-trigger="click" hx-get="/test"></div>')
452+
div.click()
453+
this.server.respond()
454+
this.server.respond()
455+
setTimeout(function() {
456+
getWorkArea().innerHTML.should.equal('<div>Yay! Welcome</div>')
457+
var path = sessionStorage.getItem('htmx-current-path-for-history')
458+
path.should.equal('/abc123')
459+
done()
460+
}, 30)
461+
})
462+
413463
it('should refresh page on HX-Refresh', function() {
414464
var refresh = false
415465
htmx.location = { reload: function() { refresh = true } }

www/content/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ or
6565
* `values` - values to submit with the request
6666
* `headers` - headers to submit with the request
6767
* `select` - allows you to select the content you want swapped from a response
68+
* `pushUrl` - can be `'true'` or a path to push a URL into browser location history
6869

6970
##### Example
7071

www/content/headers/hx-location.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Path is required and is url to load the response from. The rest of the data mirr
3030
* `values` - values to submit with the request
3131
* `headers` - headers to submit with the request
3232
* `select` - allows you to select the content you want swapped from a response
33+
* `pushUrl` - set to `'false'` or a path string to prevent or override the URL pushed to browser location history
3334

3435
## Notes
3536

0 commit comments

Comments
 (0)