Jump to content
marcus

[solved] No $input->post data when using AJAX/axios.post()

Recommended Posts

Hi there,

I ran into a problem posting form data via AJAX. Of course I did some research on the topic via Google, this forum and looking into ProcessWire's core code and found the following steps...

  • Setting headers to 'X-Requested-With', 'XMLHttpRequest'
  • Using a trailing slash

...but to no avail. As you can see in the following code I log the response, in this case just a var_dump() of wire("input")->post, but i just get

response: object(ProcessWire\WireInputData)#240 (0) {
}

Here's my code in total. It's simplified, but should work, but for some reason does not. Could any of you point me towards the solution/my fallcy? Thanks in advance! :-)

<?php

if (wire("config")->ajax) {
    if (wire("input")->post) {

        var_dump(wire("input")->post);

    }
} else {
    ?>
    <div id="app">
        <form action="./" method="post" v-on:submit.prevent="getFormValues">
            <label><input type="radio" name="yes_no" id="yes"
                  <?= ($page->yes_no == "1") ? "checked" : "" ?>
                          value="1"/>Ja</label>
            <label><input type="radio" name="yes_no" id="no"
                  <?= ($page->yes_no == "2") ? "checked" : "" ?>
                          value="2"/>Nein</label>
            <button type="submit">Go</button>
            <p>{{ yes_no }}</p>
        </form>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <script>

		new Vue({
			el: '#app',
			data: {
				yes_no: '(unbeantwortet)'
			},
			methods: {
				getFormValues: function (e) {
					this.yes_no = e.target.elements.yes_no.value;

					axios.post('./', {
						yes_no: this.yes_no
					}, {
						headers: {
							'X-Requested-With': 'XMLHttpRequest',
							'Content-Type': 'application/json'
						}
					})
						.then(function (response) {
							console.log("response:", response.data);
						})
						.catch(function (error) {
							console.log("error:", error);
						});
				}
			}
		});
    </script>

<?php } ?>

// edit:

I forgot to mention that the POST request is sent (I can track it in developer tools) and it includes the data I'm intending to send. So I really assume it is a reception problem.

Bildschirmfoto-2018-03-08-um-10_10_19.jpg.86311d2eeb8c88545e4b6dd1074a22e2.jpg

Edited by marcus
Mark as solved

Share this post


Link to post
Share on other sites

ProcessWire simply does not handle data submitted as json in the request body. It does only handle the php native formats, which are what <form/> can submit.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks for the enlightenment! I obviously deal to much with Laravel lately, so I somehow ruled out this possibility....

Share this post


Link to post
Share on other sites

For anyone stumbling over this topic, here's the solution (don't forget this is not production code - sanitize your data!). Make sure you are adding the Querystring (Qs) lib somehow

					axios.post('./',
						Qs.stringify({
							yes_no: this.yes_no
						}), {
							headers: {
								'X-Requested-With': 'XMLHttpRequest',
								'Content-type': 'application/x-www-form-urlencoded'
							}
						})
						.then(function (response) {
							console.log("response:", response.data);
						})
						.catch(function (error) {
							console.log("error:", error);
						});

 

  • Like 1

Share this post


Link to post
Share on other sites
On 3/8/2018 at 10:40 AM, LostKobrakai said:

Yeah most frameworks nowadays automatically parse json data into post data.

Would be nice to have fetch() get / post handled by $input in PW.

 

@marcus

On 3/8/2018 at 10:48 AM, marcus said:

For anyone stumbling over this topic, here's the solution (don't forget this is not production code - sanitize your data!). Make sure you are adding the Querystring (Qs) lib somehow

Which library do you use?

Share this post


Link to post
Share on other sites

Yes, but I can't use the PW $input, right?

 

But found a solution with FormData and without (!) Content-Type Header 

 

Share this post


Link to post
Share on other sites

Yeah, that doesn't come through on the $input variable, so you'd have to grab it yourself. I've pushed a PR to include it in the $input variable as it makes sense for ProcessWire to support that out of the box. @ryan

  • Like 1

Share this post


Link to post
Share on other sites

With FormData added to the fetch call $input / $_POST is populated! So with fetch it can be fixed at client side.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By louisstephens
      I have been messing around with creating pages from ajax requests, and it has gone swimmingly thus far. However, I am really struggling with creating a page and saving an image via ajax. 
      The form:
      <form action="./" role="form" method="post" enctype="multipart/form-data"> <div> <input type="text" id="preview" name="preview" placeholder="Image Title"> </div> <div> <input type="file" id="preview-name" name="preview-name"> </div> <div> <select id="select-tags" name="select-tags"> <?php $tags = $pages->find("template=tag"); ?> <option value="">Select Your Tags</option> <?php foreach ($tags as $tag) : ?> <option value="<?= $tag->name; ?>"><?= $tag->name; ?></option> <?php endforeach; ?> </select> </div> <div> <button type="button" id="submit-preview" name="submit" class="">Upload Images</button> </div> </form>  
      The ajax in my home template:
      $('#submit-preview').click(function(e) { e.preventDefault(); title = $("#preview").val(); image = $("input[name=preview-name]"); console.log(title); console.log(image); data = { title: title, image: image //not sure if this is actually needed }; $.ajax({ type: 'POST', data: data, url: '/development/upload-preview/', success: function(data) { console.log("Woo"); }, error: function(xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } }); }); And finally in my ajax template:
      $imagePath = $config->paths->assets . "files/pdfs/"; //was from an older iteration $title = $sanitizer->text($_POST['title']); $image = $sanitizer->text($_POST['image']); $p = new Page(); $p->template = "preview"; $p->parent = $pages->get("/previews/"); $p->name = $title; $p->title = $title; $p->save(); $p->setOutputFormatting(false); $u = new WireUpload('preview_image'); $u->setMaxFiles(1); $u->setOverwrite(false); $u->setDestinationPath($p->preview_image->path()); $u->setValidExtensions(array('jpg', 'jpeg', 'gif', 'png', 'pdf')); foreach($u->execute() as $filename) { $p->preview_image->add($filename); } $p->save(); I can complete the file upload but just using a simple post to the same page and it it works well, but I was really trying to work out the ajax on this so I could utilize some modals for success on creation (and to keep my templates a little cleaner). When I do run the code I have, a new/blank folder is created under assets, and a new page is created with the correct title entered. However, no image is being processed. I do get a 200 status in my console. I have searched google for help, but everything seems to be slightly off from my needs. If anyone could help point me in the right direction I would greatly appreciate it. 
    • By louisstephens
      So I am using ajax to upload an image, but I am getting the error "Method WireUpload:: save does not exist or is not callable". I am not quite sure how to go about fixing this (at the moment).
      elseif($config->ajax && $input->urlSegment1 == "upload-preview") { $u = $config->paths->assets . "files/pdfs/"; $title = $sanitizer->text($_POST['title']); $p = new Page(); $p->template = "preview"; $p->parent = $pages->get("/previews/"); $p->name = $title; $p->title = $title; $p->save(); $p->setOutputFormatting(false); $u = new WireUpload('preview_image'); $u->setMaxFiles(1); $u->setOverwrite(false); $u->setDestinationPath($p->preview_image->path()); $u->setValidExtensions(array('jpg', 'jpeg', 'gif', 'png', 'pdf')); foreach($u->execute() as $filename) { $p->preview_image->add($filename); } $u->save(); } I compared my code to something I did previously (though previously I just posted to the current template file, not through ajax) which works, but this doesnt seem to be working. I have the _init.php file prepending as well. Does anyone have any ideas of what might be happening?
    • By Brian Scramlin
      I just wanted to share that I added an AJAX-powered gallery to an artist website that I developed and host: https://jackpinecreations.com/gallery/

      There were two things that frustrated me about creating this. Perhaps you can show me a better way.
      1. After creating my processing script, which I placed under /templates/scripts/get-items.php, I realized that I would get a 403, due to ProcessWire's routing and security. This forced me to have to create a template and page for this little script. This was frustrating simply because it seemed unnecessarily confusing. But worse, see #2.
      2. I usually use config.php to prepend and append each of my templates with a head.inc and foot.inc, which keeps my templates easy to use and I don't have to go and use the GUI to do so on each template separately. However, since I realized I needed to create a new template and page so as to access it, whenever I sent POST params to it, I would get the header and footer along with it!!! I could find no workarounds and had to remove the pre/append calls in config.php and use the GUI on each template individually.  
      Code Below if you're interested:
      HTML and JavaScript (forgive my sad JavaScript skills, I know this can be tightened up)
      <!-- Begin Grid --> <div class="container mt-4"> <div id="gallery" class="row"> <?php foreach ($page->children("limit=9") as $child): ?> <div class="col-6 col-md-4 gallery-item"> <a href="<?= $child->url ?>" title="View <?= $child->title ?>"> <img class="gallery-item" src="<?= $child->item_featured_image->size(640, 640)->url ?>" alt="<?= $child->title ?> Image"> </a> </div> <?php endforeach; ?> </div> </div> <!-- End Grid --> <div class="center-block text-center"> <button id="get-more-items" type="button" name="get-more-items" class="btn-vintage">Load More</button> </div> <script type="text/javascript"> var buttonGetItems = document.getElementById("get-more-items"); var indexStart = 0; buttonGetItems.addEventListener("click", function() { indexStart += 9; $.ajax({ url: '<?= $pages->get(1186)->url ?>', type: "POST", dataType:'json', // add json datatype to get json data: ({page_id: <?= $page->id ?>, index_start: indexStart}), success: function(data){ console.log(data); if (data[1]) { //for each element, append it. $.each(data, function(key, value) { $("#gallery").append(value); }); } else { $("#get-more-items").after('<p class="center-block text-center">There are no more items to load.</p>'); $("#get-more-items").remove(); } } }); }); </script> Processing Script
      <?php $items_array = []; $i = 0; foreach ($pages->get($input->post->page_id)->children->slice($input->post->index_start, 9) as $child) { $i++; $items_array[$i] = "<div class='col-6 col-md-4 gallery-item'> <a href='$child->url' title='View $child->title'> <img src='{$child->item_featured_image->size(640,640)->url}' alt='$child->title Image'> </a> </div>"; } echo json_encode($items_array); I love ProcessWire for hundreds of reasons, but I've been using AJAX more and more, and I'm not liking having to create templates to access scripts. 
      Any advice?
    • By celfred
      Hello,
      I'm facing a weird issue here. I have a page loaded with this code inside (my comments in line ends) :

      if ($session->allPlayers) { // Set in a head.inc file. I have also a $session->set('allTeams', $allTeams); in my head.inc   $allPlayers = $session->allPlayers; } else {   $allPlayers = getAllPlayers($user, false);   $session->set('allPlayers', $allPlayers); } bd($session->getAll()); // HERE, I get a number of 11 variables which is what I expect In the same page, I have a link pointing to ajaxContent.php that loads stuff via Ajax.
      I just write this in my ajaxContent.php to test :

      bd($session->getAll()); // HERE, I get only 9 variables. All my newly set $session variables ($allTeams and $allPlayers) are not conveyed to ajaxContent.php ??? Would you have any idea why is that ??? Another thing : I have a $session->headMenu set in my head.inc, and this one works fine. I can retrieve it in my ajaxContent.php page.
      I've tried cleaning all caches but it doesn't change anything 😞 
      At first, I expected it to be a 15-minute update to my site... It turns out to be a 2-hour issue and I'm still  stuck.
      Thanks for your ideas ! 
    • By louisstephens
      So I have a template called "development" where I am testing out a few ideas etc set up on a local mamp server. I also have a page called "ajax" using a template called ajax. From my development template, I am posting a form using ajax and all is working quite well:
      $('.test').click(function(event) { event.preventDefault(); redirectUrl = $(this).data('redirect'); var data = { firstName: $("#firstname").val(), lastName: $("#lastname").val(), email: $("#email").val(), phone: $("#phone").val(), redirectUrl: redirectUrl }; $.ajax({ type: "POST", url: "localhost:8888/sandbox/ajax/form/", data: data, success: function() { console.log(this.data); top.window.location = redirectUrl; }, failure: function() { console.log(this.data); } }); And in my ajax template:
      if($input->urlSegment == 'form'){ if ($_POST) { //handle the post } } The redirectUrl is a data attribute I added in to the button (that launches the form in a modal) that pulls in from a field in processwire. Everything works just fine locally, but when I export everything to a live site it fails. It will work 1 time and redirect, but if you go back to resubmit, it submits the data but won't redirect. Can anyone see any glaring issue here, or have a better way around this?
      ------------------------------
      So, it turns out the request to /ajax/form/ was being canceled. It still handled the POST request, but never sent back a 200 to show "success". Adding in 
      return false; at the end of my .onclick solved the issue. It is strange though as I have never had this issue before.
×
×
  • Create New...