2009-09-22 6 views
4

J'ai une page web avec un formulaire. Lorsque l'utilisateur soumet le formulaire, je souhaite que le serveur redirige le navigateur vers une page différente de l'action du formulaire. En ce moment, je le fais en utilisant la fonction header de PHP pour envoyer un code d'état 302. Ça fonctionne bien.Formulaire qui redirige le navigateur lorsqu'il est accédé par un formulaire régulier ou par une requête Ajax - est-ce possible?

J'essaye de faire que la page sur le serveur redirige le navigateur de la même manière, indépendamment du fait qu'il a été soumis normalement (sans Javascript) ou par l'intermédiaire d'Ajax. J'ai essayé de le faire en définissant l'emplacement de la fenêtre à l'URL de l'en-tête Location. J'utilise jQuery, et de faire un appel comme celui-ci:

$.ajax({ 
    url: this.action, 
    type: "POST", 
    data: getFormData(this), 
    complete: function(request) { 
     window.location.assign(request.getResponseHeader("Location")); 
    } 
}); 

Toutefois, cela ne fonctionne pas. Après y avoir réfléchi, j'ai réalisé que ce n'était pas très surprenant. Dans une requête Ajax, le navigateur est supposé gérer de façon transparente les réponses de redirection telles que les codes 302 avant de changer le readyState. Lorsque la fonction complète s'exécute, elle recherche l'en-tête Location dans la destination finale et ne la trouve pas. En tant qu'expérience, j'ai ensuite essayé d'envoyer un code d'état 200 avec un en-tête Location. J'ai essayé la requête Ajax et ça a bien fonctionné. Cependant, quand j'ai fait la soumission non-Ajax, cela n'a pas fonctionné. Le navigateur s'est rendu sur la page d'action du formulaire et y est resté, comme s'il ignorait l'en-tête Location.

Y a-t-il un moyen de rediriger la même page dans les deux cas, sans que le serveur ait à savoir si la requête est une requête Ajax?

Dans le cas où cela importe, j'ai essayé le formulaire dans divers navigateurs (IE8, IE7, IE6, Firefox 3.5, Chrome) avec des résultats similaires à chaque fois. En outre, je fais une demande de publication pour éviter de tomber sur la limite de longueur d'URL de 2083 caractères d'IE.

Répondre

0

Si l'utilisateur est redirigé malgré tout, pourquoi l'Ajax? Le but d'Ajax est de faire des changements sur la page sans actualisation de la page, donc la technique que vous utilisez ressemble un peu à la construction d'une imprimante qui sort dans une trémie de déchiqueteuse.

+0

Peut-être que s'il y a une erreur il n'y a pas redirect par exemple, des trucs de type de validation – rojoca

+0

Bonne question. Le même script sur le serveur est utilisé par de nombreux formulaires sur des pages différentes, dont certaines ne sont pas bien conçues et essayent de soumettre en utilisant Ajax, sans aucune bonne raison de le faire. Cela peut être une solution de contournement temporaire jusqu'à ce que je puisse corriger ces formulaires. En outre, je suis curieux de savoir si cela peut être fait, car il peut être utile un jour. Je peux vouloir que mon site utilise Ajax pour certaines cloches et sifflets, mais fonctionne toujours pour les clients sans support Javascript. De plus, il se peut que je doive faire une requête Ajax et rester sur la même page ou rediriger, selon ce que le serveur décide. –

0

Je voudrais en savoir plus sur votre cas d'utilisation pour cela. D'après ce que je comprends votre essayant d'obtenir votre application pour charger une page basée sur l'en-tête 'Location' d'un appel Ajax en son sein? Je demanderais pourquoi?

Un en-tête HTTP ne semble être le bon endroit pour obtenir cette information de. Votre application ne fait-elle pas essentiellement une requête indiquant "Où puis-je rediriger?". Il n'y a aucune raison pour que la réponse Ajax doive répondre avec un en-tête 302 et un emplacement. Pourquoi ne pas simplement répondre avec JSON ou XML qui contient la nouvelle URL?

Modifier: Relisez simplement votre pénultième paragraphe. Je ne suis pas sûr qu'il existe un bon moyen de réaliser ce que vous voulez. Le concept semble cassé à moi. :)

0

Passez un paramètre supplémentaire à votre requête ajax pour identifier facilement le type de requête. Lorsque ajax - ne redirige pas - il suffit d'envoyer url cible, puis redirigez côté client rappel ajax via location.href

comme ceci:

 
$.post('/controller/action', {formdata}, function (redirect_to) { 
    location.href = redirect_to; 
}); 
0

fonctionnera- "complet":

$.ajax({ 
    type: frm.attr('method'), 
    url: frm.attr('action'), 
    data: frm.serialize(), 
    complete: complete(xhr, status) { 
     window.location.assign(xhr.getResponseHeader("Location")); 

    } 
}); 
+0

Cela fonctionne avec la réponse 200, mais pas avec la réponse 302. Lire mon message pour plus de détails. –

0

Avez-vous essayé d'utiliser la fonction d'erreur au lieu de complète?

$.ajax({ 
    url: this.action, 
    type: "POST", 
    data: getFormData(this), 
    error: function(request) { 
     if(request.status == 302) 
      window.location.assign(request.getResponseHeader("Location")); 
    } 
}); 

jQuery envoie une réponse 3xx à la fonction d'erreur. Peut-être que l'en-tête 'Location' sera toujours disponible à ce stade.

+0

J'ai essayé quelque chose comme ça et ça n'a pas marché. Ce n'est pas censé fonctionner de cette façon. Le navigateur est supposé suivre le code 302 de manière transparente avant d'avoir la possibilité d'exécuter les fonctions complètes, de succès ou d'erreur. Voir mon commentaire précédent (http://stackoverflow.com/questions/373087/catching-302-found-in-javascript/1406899#1406899) ​​pour plus de détails. –

+0

Je vois. On dirait que vous aurez besoin de répondre avec une réponse différente pour ajax alors. Quelle douleur – rojoca

5

HTTP 302 response are consumed silently by XmlHttpRequest implementations (par exemple, la fonction ajax de jQuery). C'est une caractéristique. La façon dont j'ai résolu ceci dans le passé est de détecter XmlHttpRequests et d'émettre un "Content-Location" header (plutôt qu'un en-tête "Location"). La façon la plus transversale bibliothèque de le faire est de vérifier la "X-Requested-With" en-tête HTTP dans votre code côté serveur (jQuery, Prototype, Mootools entre autres mis cela):

if (@$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { 
    header('Content-Location: ' . $redirect_url); 
} else { 
    header('Location: ' . $redirect_url); 
} 

Vous devez toujours cas particulier votre code client:

$.ajax({ 
    // ... 
    complete: function(xhr) { 
     var redirect_url = xhr.getResponseHeader("Content-Location"); 
     if (redirect_url) { 
      window.location = redirect_url; 
     } 
    } 
}) 
0

Pourquoi ne pas avoir votre "action ajax" simplement remplir les champs de formulaire nécessaires et soumettre le formulaire à la place? De cette façon, vous aurez exactement le même comportement que lors de la soumission à la main.

0

Voici une autre option, bien que vous aurez besoin de faire quelques tests croisés navigateur:

complete: function(request) { 
    if(request.status == 200) { 
     var doc = document.open(request.getResponseHeader('Content-Type')); 
     doc.write(request.responseText); 
     doc.close(); 
    } 
} 

inconvénients majeurs: URL dans la barre d'adresse ne change pas; pourrait mettre la pagaille avec le bouton arrière/Historique

Bien que je pense @ l'idée de crescentfresh est la voie à suivre

+0

N'a pas vu 'document.open()' depuis longtemps. Ce code va juste effacer complètement la page actuelle n'est-ce pas? Intéressant ... –

+0

Oui, il remplace juste la page avec le responseText. Sur Firefox et Safari, il a également déclenché des événements onload, ne l'a pas essayé sur d'autres navigateurs. Vous évite de faire une autre requête pour une ressource que vous avez déjà. – rojoca

Questions connexes