Skip to content

Commit 8a93011

Browse files
committed
[ajax.js] Add onValidate option
1 parent 1935ea1 commit 8a93011

3 files changed

Lines changed: 174 additions & 2 deletions

File tree

assets/js/ajax.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export function sendRequest (options) {
9696
url: null,
9797
update: null,
9898
updateMode: 'update',
99+
onValidate: null,
99100
onBeforeSend: null,
100101
onSuccess: null,
101102
onError: null,
@@ -117,6 +118,15 @@ export function sendRequest (options) {
117118
})
118119
}
119120

121+
if (optionsResolver.isNotBlank(options.onValidate)) {
122+
runCallback(options.onValidate, options)
123+
}
124+
if (options.stop !== undefined && options.stop === true) {
125+
return new Promise((resolve, reject) => {
126+
resolve(null)
127+
})
128+
}
129+
120130
options.urlResolved = resolveUrl(options)
121131

122132
const callbacksSuccess = []

doc/references/ajax.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ ajax.sendRequest({
2222
| url | Url de l'action Ajax | Oui | |
2323
| update | Si défini, mise à jour du DOM avec le résultat. (voir doc de la fonction `updateDom` plus bas) | Non | |
2424
| updateMode | Méthode à utiliser pour la mise à jour du DOM (voir doc de la fonction `updateDom` plus bas) | Non | update |
25-
| onBeforeSend | [Callback(s)](js-callbacks.md#définition-des-callbacks) lancé(s) avant l'envoi de la requête. `Function(options)`. Dans le callback peut passer `options.stop = false` pour annuler la requête. | Non | |
25+
| onValidate | [Callback(s)](js-callbacks.md#définition-des-callbacks) lancé(s) avant toute préparation de la requête: avant la résolution de l'URL, avant le dispatch de l'événement `ec-crud-ajax-before-send` et avant le callback `onBeforeSend`. `Function(options)`. Dans le callback peut passer `options.stop = true` pour annuler la requête. Voir *Différence entre `onValidate` et `onBeforeSend`* plus bas | Non | |
26+
| onBeforeSend | [Callback(s)](js-callbacks.md#définition-des-callbacks) lancé(s) avant l'envoi de la requête, après le dispatch de l'événement `ec-crud-ajax-before-send`. `Function(options)`. Dans le callback peut passer `options.stop = true` pour annuler la requête. Voir *Différence entre `onValidate` et `onBeforeSend`* plus bas | Non | |
2627
| onSuccess | [Callback(s)](js-callbacks.md#définition-des-callbacks) lancé(s) en cas de succès (code de réponse HTTP 200-299). `Function(data, response)`. <ul><li>`data`: Donnée de la réponse. Voir option `responseDataType` pour le format attendu</li><li>`response`: Objet de type [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)</li></ul> | Non | |
2728
| onError | [Callback(s)](js-callbacks.md#définition-des-callbacks) lancé(s) en cas d'erreur (code de réponse HTTP ≠ 200-299 ou erreur avant la réponse). `Function(statusText, response)` <ul><li>`statusText`: [statusText](https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText) de la réponse (si réponse). Sinon mesage d'erreur au format string</li><li>`response`: Objet de type [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) si réponse, nulm sinon</li></ul> | Non | |
2829
| onComplete | [Callback(s)](js-callbacks.md#définition-des-callbacks) lancé(s) après les callbacks `onSuccess` ou `onError`. `Function(statusText, response)`. Voir options `onSuccess` et `onError` pour détails sur `statusText` et `response` | Non | |
@@ -34,14 +35,29 @@ ajax.sendRequest({
3435
| cache | Utilise ou non le cache | Non | false |
3536
| options | Tableau d'options de la fonction [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) | Non | { } |
3637

38+
**Différence entre `onValidate` et `onBeforeSend` :**
39+
40+
Les deux callbacks reçoivent les options résolues et permettent d'annuler la requête avec `options.stop = true`,
41+
mais ils ne sont pas lancés au même moment :
42+
43+
* `onValidate` est lancé avant toute préparation de la requête : avant la résolution de l'URL, avant la construction des
44+
options de [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch), avant le dispatch de l'événement
45+
`ec-crud-ajax-before-send` et avant le callback `onBeforeSend`. À utiliser pour décider **si** la requête doit avoir
46+
lieu (demande de confirmation à l'utilisateur, validation métier...), ou pour modifier les options `url` et `query`.
47+
Comme l'événement `ec-crud-ajax-before-send` n'est pas encore dispatché, une annulation à ce stade n'exécute aucun de
48+
ses listeners.
49+
* `onBeforeSend` est lancé quand la requête est prête, juste avant son envoi et après le dispatch de l'événement
50+
`ec-crud-ajax-before-send`. À utiliser pour préparer l'envoi de la requête. À ce stade, l'URL est déjà résolue (voir
51+
`options.urlResolved`) : modifier l'option `url` n'a donc plus d'effet.
52+
3753
**Promesses :**
3854

3955
La fonction `sendRequest` retourne une promesse.
4056
* En cas de code de réponse HTTP 200-299, la promesse résout l'objet [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) représentant la réponse à la requête.
4157
* En cas de code de réponse HTTP autre 200-299:
4258
* Si l'option `successfulResponseRequired` est à `false`, alors la promesse résout l'objet [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) représentant la réponse à la requête.
4359
* Sinon la promesse est rejetée.
44-
* En cas d'annulation de la requête (par le callback `onBeforeSend` ou les événements `ec-crud-ajax` / `ec-crud-ajax-before-send`), la promesse résout une valeur nulle.
60+
* En cas d'annulation de la requête (par les callbacks `onValidate` / `onBeforeSend` ou les événements `ec-crud-ajax` / `ec-crud-ajax-before-send`), la promesse résout une valeur nulle.
4561
* En cas d'erreur lors de l'exécution de la requête, la promesse est rejetée.
4662
* En cas d'erreur lors la lecture de la réponse, la promesse est rejetée.
4763
* En cas d'erreur de configuration, la promesse est rejetée.

tests/assets/js/ajax.spec.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,130 @@ describe('Test Ajax.sendRequest', function () {
737737
expect(callbackBeforeSend).toHaveBeenCalled()
738738
})
739739

740+
it('Send request with onValidate option', async function () {
741+
const callbackSuccess = jasmine.createSpy('success')
742+
const callbackValidate = jasmine.createSpy('validate')
743+
const callbackBeforeSend = jasmine.createSpy('beforeSend')
744+
const eventBeforeSend = jasmine.createSpy('event-before-send')
745+
746+
$(document).on('ec-crud-ajax-before-send', function (event) {
747+
eventBeforeSend()
748+
})
749+
750+
const promise = ajax.sendRequest({
751+
url: '/goodRequest',
752+
onValidate: function (options) {
753+
expect(options).toBeInstanceOf(Object)
754+
expect(options.url).toEqual('/goodRequest')
755+
expect(options.urlResolved).toBeUndefined() // The URL is not resolved yet
756+
callbackValidate()
757+
},
758+
onBeforeSend: function (options) {
759+
callbackBeforeSend()
760+
},
761+
onSuccess: function (data, response) {
762+
callbackSuccess()
763+
}
764+
})
765+
766+
const response = await promise
767+
768+
expect(response).toBeInstanceOf(Response)
769+
expect(jasmine.Ajax.requests.mostRecent().url).toMatch('/goodRequest')
770+
expect(callbackValidate).toHaveBeenCalledBefore(eventBeforeSend)
771+
expect(eventBeforeSend).toHaveBeenCalledBefore(callbackBeforeSend)
772+
expect(callbackBeforeSend).toHaveBeenCalledBefore(callbackSuccess)
773+
expect(callbackSuccess).toHaveBeenCalled()
774+
775+
$(document).off('ec-crud-ajax-before-send')
776+
})
777+
778+
it('Send request canceled by onValidate option', async function () {
779+
const callbackSuccess = jasmine.createSpy('success')
780+
const callbackValidate = jasmine.createSpy('validate')
781+
const callbackBeforeSend = jasmine.createSpy('beforeSend')
782+
const eventBeginning = jasmine.createSpy('event-beginning')
783+
const eventBeforeSend = jasmine.createSpy('event-before-send')
784+
785+
$(document).on('ec-crud-ajax', function (event) {
786+
eventBeginning()
787+
})
788+
$(document).on('ec-crud-ajax-before-send', function (event) {
789+
eventBeforeSend()
790+
})
791+
792+
const promise = ajax.sendRequest({
793+
url: '/goodRequest',
794+
onValidate: function (options) {
795+
expect(options).toBeInstanceOf(Object)
796+
expect(options.url).toEqual('/goodRequest')
797+
callbackValidate()
798+
options.stop = true
799+
},
800+
onBeforeSend: function (options) {
801+
callbackBeforeSend()
802+
},
803+
onSuccess: function (data, response) {
804+
callbackSuccess()
805+
}
806+
})
807+
808+
const response = await promise
809+
810+
expect(response).toBeNull()
811+
expect(jasmine.Ajax.requests.mostRecent()).toBeUndefined() // No request is sent
812+
expect(callbackValidate).toHaveBeenCalled()
813+
expect(eventBeginning).toHaveBeenCalled()
814+
expect(eventBeforeSend).not.toHaveBeenCalled() // The event is not dispatched
815+
expect(callbackBeforeSend).not.toHaveBeenCalled()
816+
expect(callbackSuccess).not.toHaveBeenCalled()
817+
818+
$(document).off('ec-crud-ajax')
819+
$(document).off('ec-crud-ajax-before-send')
820+
})
821+
822+
it('Send request without onValidate option', async function () {
823+
const callbackSuccess = jasmine.createSpy('success')
824+
const callbackComplete = jasmine.createSpy('complete')
825+
const callbackBeforeSend = jasmine.createSpy('beforeSend')
826+
const eventBeginning = jasmine.createSpy('event-beginning')
827+
const eventBeforeSend = jasmine.createSpy('event-before-send')
828+
829+
$(document).on('ec-crud-ajax', function (event) {
830+
eventBeginning()
831+
})
832+
$(document).on('ec-crud-ajax-before-send', function (event) {
833+
expect(event.detail.options.onValidate).toBeNull() // Default value
834+
eventBeforeSend()
835+
})
836+
837+
const promise = ajax.sendRequest({
838+
url: '/goodRequest',
839+
onBeforeSend: function (options) {
840+
callbackBeforeSend()
841+
},
842+
onSuccess: function (data, response) {
843+
callbackSuccess()
844+
},
845+
onComplete: function (statusText, response) {
846+
callbackComplete()
847+
}
848+
})
849+
850+
const response = await promise
851+
852+
expect(response).toBeInstanceOf(Response)
853+
expect(jasmine.Ajax.requests.mostRecent().url).toMatch('/goodRequest')
854+
expect(eventBeginning).toHaveBeenCalledBefore(eventBeforeSend)
855+
expect(eventBeforeSend).toHaveBeenCalledBefore(callbackBeforeSend)
856+
expect(callbackBeforeSend).toHaveBeenCalledBefore(callbackSuccess)
857+
expect(callbackSuccess).toHaveBeenCalledBefore(callbackComplete)
858+
expect(callbackComplete).toHaveBeenCalled()
859+
860+
$(document).off('ec-crud-ajax')
861+
$(document).off('ec-crud-ajax-before-send')
862+
})
863+
740864
it('Test ec-crud-ajax-before-send event', async function () {
741865
const callbackSuccess = jasmine.createSpy('success')
742866
const callbackBeforeSend = jasmine.createSpy('beforeSend')
@@ -1165,6 +1289,28 @@ describe('Test Ajax.click', function () {
11651289
$(document).off('ec-crud-ajax-click-auto-before', '#clickToTest')
11661290
})
11671291

1292+
it('Send auto-request canceled by onValidate option', async function () {
1293+
$('body').append('<button class="html-test" data-ec-crud-toggle="ajax-click" id="clickToTest" data-ec-crud-ajax-url="/goodRequest" data-ec-crud-ajax-on-validate="my_callback_on_validate">Go !</button>')
1294+
1295+
const callbackValidate = jasmine.createSpy('validate')
1296+
1297+
callbackManager.registerCallback('my_callback_on_validate', function (options) {
1298+
callbackValidate()
1299+
options.stop = true
1300+
})
1301+
1302+
$('#clickToTest').get(0).click()
1303+
1304+
await wait(() => {
1305+
return false
1306+
}, 500)
1307+
1308+
expect(jasmine.Ajax.requests.mostRecent()).toBeUndefined()
1309+
expect(callbackValidate).toHaveBeenCalled()
1310+
1311+
$(document).off('ec-crud-ajax-click-auto-before', '#clickToTest')
1312+
})
1313+
11681314
it('Send auto-request with button and error', async function () {
11691315
$('body').append('<button class="html-test" data-ec-crud-toggle="ajax-click" id="buttonToTest">Go !</a>')
11701316
spyOn(window.console, 'error')

0 commit comments

Comments
 (0)