diff --git a/src/index.js b/src/index.js index 423082b..9b2b725 100644 --- a/src/index.js +++ b/src/index.js @@ -16,7 +16,7 @@ function Ajax(Alpine) { window.location.reload(true) }) - Alpine.directive('target', (el, { modifiers, expression }, { cleanup }) => { + Alpine.directive('target', (el, { modifiers, expression }, { evaluate, cleanup }) => { let config = { targets: parseIds(el, expression), events: true, @@ -25,6 +25,8 @@ function Ajax(Alpine) { sendConfig.set(el, config) + config.headers = evaluate(Alpine.bound(el, 'x-headers', '{}')) + if (isLocalLink(el)) { cleanup(listenForNavigate(el, config)) } else if (isForm(el)) { @@ -62,10 +64,18 @@ function Ajax(Alpine) { } } + let headers = options.headers + if (!headers) { + headers = el.hasAttribute('x-headers') + ? Alpine.evaluate(el, Alpine.bound(el, 'x-headers', '{}')) + : {} + } + let request = { action, method, body, + headers, referrer: source(el), } @@ -141,6 +151,7 @@ function listenForNavigate(el, config) { event.stopPropagation() let request = navigateRequest(el) + request.headers = config.headers || {} let targets = addSyncTargets(findTargets(config.targets)) try { @@ -180,6 +191,7 @@ function listenForSubmit(el, config) { event.stopPropagation() let request = formRequest(el, event.submitter) + request.headers = config.headers || {} let targets = addSyncTargets(findTargets(config.targets)) try { @@ -268,10 +280,14 @@ async function render(request, targets, el, config) { if (!dispatch(el, 'ajax:before')) return + let targetIds = [] targets.forEach(target => { target.setAttribute('aria-busy', 'true') + targetIds.push(target.id) }) + request.headers['X-Alpine-Request'] = 'true' + request.headers['X-Alpine-Target'] = targetIds.join(' ') let response = await send(request, config.followRedirects) if (response.ok) { diff --git a/src/send.js b/src/send.js index 38c037c..0e9252f 100644 --- a/src/send.js +++ b/src/send.js @@ -1,6 +1,6 @@ let jobs = {} -export async function send({ method, action, body, referrer }, followRedirects) { +export async function send({ method, action, body, referrer, headers }, followRedirects) { // When duplicate `GET` requests are issued we'll proxy // the initial request to save network roundtrips. let proxy @@ -19,7 +19,7 @@ export async function send({ method, action, body, referrer }, followRedirects) referrer = referrer || window.location.href let response = fetch(action, { - headers: { 'X-Alpine-Request': 'true' }, + headers, referrer, method, body, diff --git a/tests/ajax.cy.js b/tests/ajax.cy.js index 597dc25..8a8c972 100644 --- a/tests/ajax.cy.js +++ b/tests/ajax.cy.js @@ -19,6 +19,35 @@ test('GET request data is added to the URL', } ) +test('custom headers can be set through options', + html``, + ({ intercept, get, wait }) => { + intercept('POST', '/tests', { + statusCode: 200, + body: '

Success

Replaced
' + }).as('response') + get('button').click() + wait('@response').its('request.headers').should('have.property', 'x-test', 'test') + } +) + +test('[x-headers] can set custom headers', + html``, + ({ intercept, get, wait }) => { + intercept('POST', '/tests', { + statusCode: 200, + body: '

Success

Replaced
' + }).as('response') + get('button').click() + wait('@response').its('request.headers').should('have.property', 'x-test', 'test') + } +) + test('follows redirects by default', html``, + ({ intercept, get, wait }) => { + intercept('POST', '/tests', { + statusCode: 200, + body: '

Success

Replaced
' + }).as('response') + get('button').click() + wait('@response').its('request.headers').should('have.property', 'x-test', 'test') + } +) + +test('[ajax:before] event is fired', html`

CHANGE ME

`, ({ intercept, get, wait }) => { intercept('POST', '/tests', { @@ -185,7 +197,7 @@ test('ajax:before event is fired', } ) -test('ajax:before can cancel AJAX requests', +test('[ajax:before] can cancel AJAX requests', html`

Replace me

`, ({ intercept, get, wait }) => { cy.on('fail', (error, runnable) => { @@ -204,7 +216,7 @@ test('ajax:before can cancel AJAX requests', } ) -test('formnoajax can cancel AJAX requests', +test('[formnoajax] can cancel AJAX requests', html`

Replace me

`, ({ intercept, get, wait }) => { cy.on('fail', (error, runnable) => { diff --git a/tests/link.cy.js b/tests/link.cy.js index af3c24d..9606071 100644 --- a/tests/link.cy.js +++ b/tests/link.cy.js @@ -45,3 +45,15 @@ test('target can be set in attribute', }) } ) + +test('[x-headers] sets request headers', + html`
Link`, + ({ intercept, get, wait }) => { + intercept('GET', '/tests', { + statusCode: 200, + body: '

Success

Replaced
' + }).as('response') + get('a').click() + wait('@response').its('request.headers').should('have.property', 'x-test', 'test') + } +)