Jump to content

Ajax File Upload before page is created


bfncs
 Share

Recommended Posts

Hello everyone,

I was just asking myself whether any has already created some kind of ajax file upload in Processwire for a page that is not yet created.

As a simple example, think of a user registration form with the usual fields including an avatar image. I'd like to use something like Plupload, Dropzone.js or a similiar Ajax file uploader to upload the file asynchronously already before the rest of the form is processed.

That would make it possible to i.e.

  • directly show the user a resized preview of his avatar image,
  • build forms with a lot of file uploads that would otherwise break the file upload limit,
  • and probably a lot more neat features.

It would be essential, that it is usable like a standard backend file upload/image field afterwards, it would be even better if files are also located in the id-named folder in assets/ after submitting the leftover form.

The way I thought about how to do this would pack the following functionality in a plugin:

  1. Use some existing Ajax file uploader to get the file from client to server.
  2. There, a module takes care of the request, saves the file to some temporary folder and answers with an (id) reference to the image to work with it later.
  3. Ideally - if it's an image - it would already be possible to get a resized version of the image to provide a live preview.
  4. When the form finally get's submitted, the request includes the reference to the file.
  5. On the server, the image field is constructed as usual and the file itself get's moved to the "default" location. The temporary reference is deleted.

One problem I see with this approach, is that after a while you will have a lot of unused files and references but that's no problem that a cron job with some code to get rid of old stuff couldn't solve.

Having written all that down:

Is there anything that already solves more or less what I described?

And if not: do you see any problems with my outline or do you have a more elegant idea to implement this?

Any feedback on this is appreciated, for sure.

Marc

Link to comment
Share on other sites

I did this already and the method that I used was having the images on their own page instead of on the user page (images were avatars for users) and having a page field on the user page to link to the image. This was more or less the process (by memory):

  1. First Ajax call for the image creates a image page under the "images" page in the tree and returns the id of the newly created page.
  2. The returned id is stored on a hidden field with javascript and sent back to the server with the rest of the form on submission.
  3. While processing the form in the server, the previously created image page is stored in the page field of the new user page.
Link to comment
Share on other sites

Hey Diogo,

thanks for your quick answer!

Your approach absolutely makes sense for user images, I already thought about going that route. But if you have something where content is user-generated but afterwards sighted and edited by an editor, it would be great to have everything on one page. And to be able to use already existing modules like apeisa's great and indespensable thumbnails module like they are meant to be used. This practically rules out your approach that will work for a lot of use cases for the things I have in mind.

But just from the fact, that you did it yourself, I assume there's no ready to use solution out there already?

Link to comment
Share on other sites

I think there's not a ready solution.

What you could do to overcome your problem is actually not that complicated, and it would only add one step to the process. Instead of storing the image page on a page field, just pull the image to a image field in the "user" page and delete the other page.

Link to comment
Share on other sites

  • 1 month later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Liam88
      Hi,
      I'm really struggling with this as it's something not in my wheelhouse. I'm creating a blog style page (a grid of cards) which has attributes.
      I have a snip of javascript which grabs values from checkboxes which are put into a value like the below:
      ?content=static_video&channel=facebook-ads_instagram-ads
      document.querySelector("form").onsubmit=ev=>{ ev.preventDefault(); let o={}; ev.target.querySelectorAll("[name]:checked").forEach(el=>{ (o[el.name]=o[el.name]||[]).push(el.value)}) console.log(location.pathname+"?"+ Object.entries(o).map(([v,f])=> v+"="+f.join("_")).join("&") ); document.location.href = location.pathname+"?"+ Object.entries(o).map(([v,f])=> v+"="+f.join("_")).join("&"); } As I'm currently refeshing the page on button click with those values the end result includes the location but can easily remove this.
      I then use this value in "input->get" to get the values which I then append to a find() rule. See code below:
      $selector = "template='adbank_pages',sort=published,include=all,status!=hidden"; // Get the channel and content inputs $channel = $input->get->channel; $content = $input->get->content; if($channel){ // Grab the channel string, explode into an array for checkbox checking and then replace _ with | to create or rules in the selector. $chanArray = explode("_", $channel); $chan = $channel = str_replace('_', '|', $channel); $selector = $selector .= ",ab_channels=$chan"; } if($content){ // Grab the content string, explode into an array for checkbox checking and then replace _ with | to create or rules in the selector. $contArray = explode("_", $content); $cont = $content = str_replace('_', '|', $content); $selector = $selector .= ",ab_content=$cont"; } if($input->get){ // If a valid input result $all = $pages->find($selector); } }else{ // If no input show them all $all = $page->children("template='adbank_pages',sort=-published,include=all,status!=hidden"); } $items = $all->find("limit=12"); // Limit the output and use pagination As mentioned above I currently refresh the page to adjust the $selector filter within the $all with a fallback $all if there are no results.
      I know I need to use AJAX to filter the content without refresh but I am really struggling with the set up. I have read multiple posts including the original by Ryan but still confused.
      If anyone can direct/help on this it would be appreciated.
      Thank you
    • By ICF Church
      Hi 👋
      Anyone else having this problem?
      Requirements:
      - Repeater (matrix & normal) with mutlilanguage fields (text, textarea…) 
      - Backend language set to something other than default (ie. German) 
      Reproduce:
      - Add a new repeater Item (ajax, I found no way to possible to disable it with matrix)

      (Notice how the default language tab is active instead of the backend language…)
      - Write something into the (default language) field
      - Try to save, if field is required, this will not work. If not required, then when reloading, the content will be inside the backend language field, instead of the default language field who was (presumably) active
      Analysis:
      When  loading  a new repeater element with ajax, the default langue tab is active, but the backend language inputfield is visible (with no visual indication). When writing into the field, it will populate the backend language. When manually clicking on the default language tab (which is already active), the field will switch to the actual default language field (which is [now] empty) (that can now be populated…)
      Also Notice, the labels of the elements to be added are in default language as well instead of the translated label (images instead of Bilder)…
      ProcessWire 3.0.148, Profields 0.0.5…
      Is it my system configuration, or does anyone else have the same issue? This is a screen recording of the problem:
      Issue: https://github.com/processwire/processwire-issues/issues/1179

      Screen Recording 2020-02-25 at 14.18.31.mov
    • By michelangelo
      Hello there,
      I am building my website, which has a dozen projects with 10 images each. Basically, I need a filtering system but built in the most efficient and user-friendly way. You can see below that the images flow sideways so being hidden, JS lazy loading was a good tool, but I just wanted to try AJAX. Is it fit for this purpose or it's more for dynamic 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. 
×
×
  • Create New...