Search the Community

Showing results for tags 'forms'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Found 32 results

  1. Hey all, Mods; please feel free to move this if it is in the incorrect place although I thought this was the best place for it. Kinda new to processwire but getting the hang of it....I am trying to build a payment form with the Stripe platform but failing miserably....I really hope someone can help! So I am building my form with the PW API and also following through this documentation here: and here: My form is pretty basic just for testing purposes right now: <form id="payment-form" class="pusher" name="payment-form" method="post" action="./#booking-form"> <?php $tokenName = $this->session->CSRF->getTokenName(); $tokenValue = $this->session->CSRF->getTokenValue(); echo '<input type="hidden" id="_post_token" name="' . $tokenName . '" value="' . $tokenValue . '"/>'; $out = ""; $out .= '<div id="card-number"></div> <div id="card-errors"></div>'; // create a new form field (also field wrapper) $form = $modules->get("InputfieldForm"); $form->action = "./"; $form->method = "post"; $form->attr("id+name",'payment-form'); // First Name $field = $modules->get("InputfieldText"); $field->skipLabel = true; $field->attr('id+name','name'); $field->attr('placeholder','Full Name'); $field->required = 1; $form->append($field); // append the field to the form // create email field $field = $modules->get("InputfieldEmail"); $field->attr('id+name','email'); $field->attr('placeholder','Email'); $field->required = 1; $form->append($field); // append the field // oh a submit button! $submit = $modules->get("InputfieldSubmit"); $submit->attr("value","SUBMIT"); $submit->attr("id+name","submit"); $submit->attr("class","cta white"); $form->append($submit); if($input->post->submit) { // user submitted the form, process it and check for errors $form->processInput($input->post); if($form->getErrors()) { // the form is processed and populated // but contains errors $out .= $form->render(); } else { foreach($input->post as $key => $value) echo htmlentities("$key = $value") . "<br />"; } } else { foreach($form->children as $input){ $out .= "<div class='col-sm-6'>{$input->render()}</div>"; } } echo $out; ?> </form> That alone works fine and returns all of the fields values after I click submit which is we add the javascript: //Stripe var stripe = Stripe('pk_test_*****************'); var elements = stripe.elements(); // Custom styling can be passed to options when creating an Element. var style = { base: { // Add your base input styles here. For example: fontSize: '16px', lineHeight: '24px' } }; // Create an instance of the card Element var card = elements.create('card', {style: style}); // Add an instance of the card Element into the `card-element` <div> card.mount('#card-number'); card.addEventListener('change', function(event) { var displayError = document.getElementById('card-errors'); if (event.error) { displayError.textContent = event.error.message; } else { displayError.textContent = ''; } }); // Create a token or display an error when the form is submitted. var form = document.getElementById('payment-form'); form.addEventListener('submit', function(event) { event.preventDefault(); stripe.createToken(card).then(function(result) { if (result.error) { // Inform the user if there was an error var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { // Send the token to your server stripeTokenHandler(result.token); } }); }); function stripeTokenHandler(token) { // Insert the token ID into the form so it gets submitted to the server var form = document.getElementById('payment-form'); var hiddenInput = document.createElement('input'); hiddenInput.setAttribute('type', 'hidden'); hiddenInput.setAttribute('name', 'stripeToken'); hiddenInput.setAttribute('value',; form.appendChild(hiddenInput); // Submit the form form.submit(); } This gives an error in the console: Uncaught (in promise) TypeError: form.submit is not a function. This is because our submit input has the name "submit". Ok thats cool...I can change that but once I do the page essentially refreshes and the form just shows again and it doesnt give me the values it did before....I guess it isnt posting? either way after I submit the form after changing the name of the submit button the form just loads again and anything inside: if($input->post->submit) doesnt seem to what gives? If anybody here has done this before with PW 3+ I would really love an example of how to use this to the point of sending information to Stripe. I have installed Stripe with composer and it would appear that I can refer to it in Processwire just problem is just getting to the point where I need to refer to it which is after the submit. I have seen the PaymentStripe module but tbh the documentation on that is somewhat lacking and im not even sure it works with the latest version of stripe? Im also not sure how to integrate that into a form either unless you use something along the lines of the example code provided after the form has been submitted but I cant even seem to submit the form to even try that and im not really sure why. Here is the PaymentStripe module page for those wondering: Any help would be greatly appreciated! Cleanboy
  2. I am implementing the ability to handle form submission using AJAX. The problem I have is that even though, as far as I can tell, I convert the AJAX-submitted JSON input into the equivalent of $input->post. When I call $form->processInput() it always throws that it appears to be forged. if ($config->ajax && $_SERVER['REQUEST_METHOD'] === 'POST') { // get the file body and decode the JSON. try { $body = file_get_contents('php://input'); $json = wireDecodeJSON($body); //wire('log')->save('info', 'ajax-json:' . print_r($json, true)); wire('log')->save('info', 'json-data:' . print_r($json['data'], true) . ' sid: ' . session_id()); $fakeinput = new WireInputData($json['data']); $form = deleteRequest('xyzzy'); $form->processInput($fakeinput); } catch (Exception $e) { http_response_code(404); echo json_encode(array('reason' => $e->getMessage())); } return; The log shows that the TOKEN and the TOKEN value are the same as when a normal form is submitted (I have both on the page for testing and can submit via normal POST as well as via AJAX). The session_id() value is the same. What am I missing? Log entries ("dumb" is the normal submit button name, "fake-text" is an empty text field, "submit" is the AJAX submit button name.) (using form-post): post Array ( [dumb] => dumb-button [TOKEN1649939534X1479234443] => f4VLZ17RlXfp9KVCQr/GIhoZ3krbuWK5 ) (using ajax-post): json-data: Array ( [fake-text] => [submit] => DELETE ENDUSERS [TOKEN1649939534X1479234443] => f4VLZ17RlXfp9KVCQr/GIhoZ3krbuWK5 )
  3. I had situations come up that just seemed like AJAX was the right way to handle interactions with the ProcessWire server - pages with an element like a button or link that should cause an action to occur but shouldn't require a form or actually following a link - it should just take the action and only update the toggle (a checkbox in this case) when the interaction is completed. Another use case is with a large page on which there are multiple possible interactions. When the page is heavy enough that redrawing results in a less than optimal user experience then it's nice to be able to submit a form without having to redraw the page in order to update the relevant parts. So with that preamble, here's what I put together. I was going to try to clean it up a bit but that has prevented me from posting this so I figured it's better to post it and clean it up if there is any interest. You'll see references to the namespace whale - the name of our project - that would ultimately be removed. There are two major components - the PHP side and the client-side. On the PHP side there are two functional areas: 1. "wrapping" an entity to be inserted into the HTML on a page Wrapping (the function 'makeContainer()' puts a predefined wrapper around one of three types of objects: FormBuilderForm, InputfieldForm, or Template). The wrapper provides context and attaches classes that allows the client JavaScript code to find the wrapper and figure out what to do with it. // // define a function that makes a "form" of a single button. // function makeButton ($label) { // get the form $form = wire('modules')->get("InputfieldForm"); $form->attr('action', './'); $form->attr('method', 'post'); $submit = wire('modules')->get("InputfieldSubmit"); $submit->attr('id+name', 'submit'); $submit->attr('value', $label); $form->add($submit); return $form; } // wrapper function to set label on submit button function requestUserDeleteList() { return makeButton('Do it!'); } // // makeContainer wraps the rendered InputfieldForm in HTML so the client JavaScript can recognize it and handle // AJAX interactions with the server. // It returns the InputfieldForm object and the HTML to be inserted into the page. Note that makeContainer // is in a different namespace so it requires the function name must be qualified with the \ProcessWire prefix. // list ($form, $deleteUsersHTML) = ajax\Request::makeContainer('do-something', '\ProcessWire\requestUserDeleteList'); 2. helping with the processing of an AJAX request that is submitted to the page. Helping with the AJAX request - the code is invoked on page load and determines where there is a valid AJAX request from something it wrapped. It also allows messages to be returned, classes to be added or removed from specific elements, redirects to be executed, or even wholesale replacement of DOM elements (with plenty of caveats). It will even update a submit key so it is possible for the client to execute a single transaction multiple times. // get a new request object for the AJAX transaction $request = new ajax\Request(); // if it isn't formatted correctly handle the error if (!$request->isValidCall()) { return $request->echoError(); } // get the data and function-specific contents (Whale Ajax Context) $data = $request->data(); $wac = wireDecodeJSON($data['wac']); // if ($request->id('wants-newsletter')) { if (!ajax\Request::hasCorrectProperties($data, ['wac', 'value'])) { return $request->echoError(__('invalid call')); } // implement function here } else if ($request->id('another-function')) { // implement function here } // it didn't match any of the AJAX IDs implemented return $request->echoError('not implemented'); The client code requires jQuery and is packaged as three separate functions because both the form and template processing share a common core set of functions. My original intent was to only load the form or non-form code as needed but they're small enough that it really doesn't matter. See attachments for the Request class and the client code. There are many helper functions. Here is a kind of an unfocused extract that illustrates using the code with more context (from an internal sandbox page): <?php namespace ProcessWire; using whale\ajax; // include server-side code for making forms and processing them require_once './utility/'; // custom version of ProcessWire/wire/core/WireFileTools.php render() that returns the // template object, not the rendered HTML require_once './utility/'; // START AJAX submitted form processing - decodes the request and stores results in $aaform. $aaform = new ajax\Request(); // // this page handles multiple ajax calls so I check to see if it is valid once and then check IDs. // It's also possible to use $aaform->isValidCall('get-user-delete-list') to check specifically // for a specific AJAX ID. The ID is the name provided to Request::makeContainer() when the object // is wrapped. It's also possible to make calls to $aaform->id('get-user-delete-list') to check // for a specific ID. // // to create the forms/input elements that are submitted via AJAX start with: // Request::makeContainer('unique-name-on-page', object) // unique-name-on-page will become the ID of the element that wraps your object. // object - one of ProcessWire\InputfieldForm, \FormBuilderForm, ProcessWire\Template. // if ($aaform->isValidCall()) { if ($aaform->id() === 'get-user-delete-list') { $form = requestUserDeleteList(); // process using the form. the Request object will check to make sure it's the right type. if (!$aaform->process($form)) { return $aaform->echoError(); } // build new form with usernames for selections to delete. the function getUsersToDelete() // returns a user count and a function that will make the form that includes the users in // a list of checkboxes. list($usercount, $formmaker) = getUsersToDelete(); // this returns a replacement to part of the existing DOM. There are limitations but it // handles adding a form or replacing an existing form. if ($usercount === 0) { $replacement = '<div id="ajax-place">No users to delete</div>'; } else { // we pass the $formmaker function to makeContainer(). It returns the form and the // rendered wrapper and form. list($xform, $xhtml) = ajax\Request::makeContainer('do-delete', $formmaker); $replacement = '<div id="ajax-place">' . $xhtml . '</div>'; } // this makes sure the return is formatted so the client can handle it correctly. in // this case a replacement in the DOM is being returned. The first argument is the // selector, the second is the HTML to replace the selected element with. return $aaform->echoReplacement('#ajax-place', $replacement); } else if ($aaform->id() === 'do-delete') { list($usercount, $formmaker) = getUsersToDelete(); // process using the form returned by $formmaker. this will check to make sure it's // the right type of form. This abstracts FormBuilder forms and InputfieldForms. if (!$aaform->process($formmaker())) { return $aaform->echoError(); } // a bunch of logic where the checked users are deleted $deleted = []; $failed = []; $data = $aaform->data(); foreach($data as $name => $value) { if ($name === $value) { $user = wire('users')->get("name=$name"); $email = $user->email; // delete the user and try to get it again to see if the delete worked wire('users')->delete($user); $u = wire('users')->get("name=$name"); if (!count($u)) { $deleted[] = $email . " ($name)"; } else { $failed[] = $email . " ($name)"; } } } $deleted_users = $failed_deletions = ''; if ($deleted) { $deleted_users = 'deleted:<br/>' . join($deleted, '<br/>') . '<br/>'; } if ($failed) { $failed_deletions = 'failed to delete:<br/>' . join($failed, '<br/>') . '<br/>'; } $replacement = '<div id="ajax-place">' . $deleted_users . $failed_deletions . '</div>'; return $aaform->echoReplacement('#ajax-place', $replacement); } else if ($aaform->id() === 'contact') { // here a FormBuilderForm is being loaded if (!$aaform->process($forms->load('contact'))) { return $aaform->echoError(); } // this sends a notice back. the client will place it in a predefined notice area. // Request::makeContainer() will create an area for notices (or you can supply one). // It is also possible to return errors; notices and errors get different classes. $msg = ajax\Request::makeNotice('bruce says hi'); return $aaform->echoSuccess($msg); } else { // it was a valid form but it doesn't match any ID that this page knows about. return $aaform->echoError('what is this?'); } } // normal processing to render the initial page follows as it was not a valid AJAX post // that is handled by Request(). That's a lot of code, so I won't post anymore. If people have interest I'm happy to explain or provide other bits of code, like the extracted function. Wrapping a template is similar to wrapping a form except that only certain HTML elements are tracked and each are sent to the server when they are clicked on (technically it varies). It handles radio buttons, checkboxes, links, and buttons (radios and checkboxes on "change" and links and buttons on "click"). So when a checkbox is checked an AJAX call will be made so it can be acted upon by the server. @microcipcip, @ryan, @valan (sorry to any if this isn't interesting to you - I did a quick scan of what looked like semi-related AJAX posts). ajaxclient.js
  4. hello! I have a site on processwire version 2.3. Can I install Form builder, and will it work?
  5. is there a simple way to render a form from the backend in frontend ( with other styles ) ? Or do i have to build everything on my own like in this post ? Thanks for any help.
  6. Why does the forms API use lists - ul, li - to style forms? It makes them much harder to control with CSS. Why not something like this? <style> .field { float: left; width: 100%; } .inputfieldheader { float: left; width: 100%; } .input { float: left; } </style> <form> <div class=field> <label class=inputfieldheader>Field one</label> <input class=input> </div> <div class=field> <label class=inputfieldheader>Field two</label> <input class=input> </div> <div class=field> <label class=inputfieldheader>Field three</label> <input class=input> </div> </form>
  7. I am trying to apply onkeyup or jquery keyup to a PW form - to autogenerate a username from a real name. This javascript/jquery works fine on test html input fields: But I can't get it to work on the fields generated by the PW forms API, even though the input id names are exactly the same. What am I missing?
  8. I have a single-page website with a contact form: <div id="wrap_form"> <form id="inquire" action="" class="uk-form"> <div class="uk-grid uk-grid-collapse"> <input type="text" id="i_name" name="name" class="uk-width" placeholder="Your Name" maxlength="250" required /> <input type="text" id="i_phone" name="phone" class="uk-width" placeholder="###-###-####" pattern="^[2-9]\d{2}-\d{3}-\d{4}$" required /> <input type="text" id="i_email" name="email" class="uk-width" placeholder="Email" pattern="/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/" maxlength="250" /> <input type="text" id="i_zipcode" name="zipcode" class="uk-width" placeholder="Zip Code" pattern="\d{5}-?(\d{4})?" /> <select name="scope" id="i_scope" class="uk-width" multiple required> <option value="" disabled>Representing...</option> <option value="residential">Residence</option> <option value="commercial">Business</option> </select> <textarea name="message" id="i_message" class="uk-width" placeholder="Message" rows="4" required></textarea> <input type="submit" name="submit" id="submit" class="uk-button uk-width" value="Send" /> <!--button type="submit" name="submit" id="submit" class="uk-button uk-width">Send <i class="fa fa-send"></i></button--> </div> </form> </div> Above is from contact.php template partial included in my _main.php output, which includes this script in the body closing: $(function() { $('.error').hide(); $("#inquire").submit(function(e) { e.preventDefault(); // validate and process form here $('.error').hide(); //var name = $("input[name='name']").val(); var name = $("input#i_name").val(); if (name == "") { $("label#name_error").show(); $("input[name='name']").focus(); return false; } //var phone = $("input[name='phone']").val(); var phone = $("input#i_phone").val(); if (phone == "") { $("label#phone_error").show(); $("input[name='phone']").focus(); //return false; } //var email = $("input[name='email']").val(); var email = $("input#i_email").val(); //var zipcode = $("input[name='zipcode']").val(); var zipcode = $("input#i_zipcode").val(); //var scope = $("select[name='scope']").val(); var scope = $("select#i_scope").val(); if (scope == "") { $("label#scope_error").show(); $("select[name='scope']").focus(); //return false; } //var message = $("textarea[name='message']").val(); var message = $("textarea#i_message").val(); if (phone == "") { $("label#message_error").show(); $("textarea[name='message']").focus(); //return false; } var dataString = 'name=' + name + '&phone=' + phone + '&email=' + email + 'zipcode=' + zipcode + 'scope=' + scope + 'message=' + message; //alert (dataString); return false; $.ajax({ type: "POST", url: "./inquiries/", data: dataString, success: function() { $('#wrap_form').html("<div id='inquired'></div>"); $('#inquired').html("<h3>Inquiry submitted!</h3>") .append("<p>Thanks, " + name + "! We will be in touch soon.</p>") .hide() .fadeIn(1500, function() { $('#inquired p').append(" <i class='fa fa-check' style='color:green'></i>"); }); } }); //return false; }); }); I tried submitting directly to a php file in templates which is forbidden so I saw that this worked for someone and no longer get an error; the form seems to submit from the frontend, however nothing results from it in the admin. Here's my inquiries.php template file: <?php $mailTo = $pages->get('/contact/')->contact_email; // sanitize form values or create empty $data = array( 'name' => $sanitizer->text($input->post->name), 'phone' => $sanitizer->text($input->post->phone), 'email' => $sanitizer->email($input->post->email), 'zipcode' => $sanitizer->text($input->post->zipcode), 'scope' => $sanitizer->text($input->post->scope), 'message' => $sanitizer->textarea($input->post->message), ); $error = ''; if($input->post->submit) { $up = $pages->get('/inquiries/'); $up->title .= "+"; $up->save(); $msg = "Name: $data[name]\n" . "Phone: $data[phone]\n" . "Email: $data[email]\n" . "Zip Code: $data[zipcode]\n" . "Job Type: $data[scope]\n" . "Message: $data[message]"; $p = new Page(); $p->title = date('Y/m/d H:i:s'); $p->parent = $pages->get('/inquiries/'); $p->template = 'inquiry'; $p->message = $msg; $p->save(); } I added the inquiries title appendage bit just for testing, but it just doesn't happen. How can I make this work/better test?
  9. I'm looking for the module(s) that contain the code used to define and process forms. I don't see anything in the dist/wire/* directories that has 'form' in the name. Does anyone know where this code is?
  10. Hi Folks, I've got a site with some contact and quote forms which get sent to my client and get saved as pages so the client has a record of the submitted forms. He'd like to analyse some of the form data. So for instance, there's a field that asks 'where did you hear about us?' with select options like 'Advertisement', 'Google', 'Recommendation', 'Magazine', etc. I'd like provide a page so the client could see how many respondents chose 'Google' vs 'Advertisement', etc. A simple tally would be fine, but then I could calculate percentages, maybe chart the results, etc. My first thought was to use $pages->count('selector') to count the pages with a certain answer. I'd know what percentage that was by comparing it to the total of saved pages for that form. But would I need to do this for each question? Is there a better way to tally/count all the answers for a given field?
  11. Greetings Everyone, ************************************************* ************************************************* EDIT NOTE: This post started as a work-in-progress discussion as I was working out the elements of a successful form. After contributions from participants in this discussion, the code below has been tested and works well. You can use the code as shown below in your ProcessWire templates! Feel free to follow up with additional quesations/comments! ************************************************* ************************************************* I have successfully built front-end forms with ProcessWire to add pages via the API. It works great -- until I had to include image uploads along with the "regular" form fields. Then it temporarily got a bit complicated. In this discussion, I show how to handle front-end submissions in ProcessWire with the goal of allowing us to create pages from custom forms. I then go a step further and show how to use the same form to upload files (images and other files). I'm hoping this discussion can illustrate the whole process. I know a lot of people are interested in using ProcessWire to do front-end submissions, and my goal for this discussion is to benefit others as well as myself! First, here's my original contact form (no file uploads): <form action="/customer-service/contact/contact-success/" method="post"> <p><label for="contactname">Name:</label></p> <p><input type="text" name="contactname"></p> <p><label for="email">E-Mail:</label></p> <p><input type="email" name="email"></p> <p><label for="comments">Comments:</label></p> <p><textarea name="comments" cols="25" rows="6"></textarea></p> <button type="submit">Submit</button></form> And here's the "contact-success" page that picks up the form entry to create ProcessWire pages: <?php // First, confirm that a submission has been made if ($input->post->contactname) { // Save in the ProcessWire page tree; map submission to the template fields $np = new Page(); // create new page object $np->template = $templates->get("contact_submission"); $np->parent = $pages->get("/customer-service/contact-us/contact-submission-listing/"); // Send all form submissions through ProcessWire sanitization $title = $sanitizer->text($input->post->contactname); $name = $sanitizer->text($input->post->contactname); $contactname = $sanitizer->text($input->post->contactname); $email = $sanitizer->email($input->post->email); $comments = $sanitizer->textarea($input->post->comments); // Match up the sanitized inputs we just got with the template fields $np->of(false); $np->title = $contactname; $np->name = $contactname; $np->contactname = $contactname; $np->email = $email; $np->comments = $comments; // Save/create the page $np->save(); } ?> This works great! After submitting the form, we go to the "Success" page, and new submissions show up in the ProcessWire page tree right away. Excellent! Now I need to add a photo field. I altered the above form so it looks like this: <form action="/customer-service/contact/contact-success/" method="post" enctype="multipart/form-data"> <p><label for="contactname">Name:</label></p> <p><input type="text" name="contactname"></p> <p><label for="email">E-Mail:</label></p> <p><input type="email" name="email"></p> <p><label for="comments">Comments:</label></p> <p><textarea name="comments" cols="25" rows="6"></textarea></p> <p>Click the "Select Files" button below to upload your photo.</p> <input type="file" name="contact_photo" /> <button type="submit">Submit</button> </form> And here's the updated "contact-success" page: <?php // First, confirm that a submission has been made if($input->post->contactname) { // Set a temporary upload location where the submitted files are stored during form processing $upload_path = $config->paths->assets . "files/contact_files/"; // New wire upload $contact_photo = new WireUpload('contact_photo'); // References the name of the field in the HTML form that uploads the photo $contact_photo->setMaxFiles(5); $contact_photo->setOverwrite(false); $contact_photo->setDestinationPath($upload_path); $contact_photo->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); // execute upload and check for errors $files = $contact_photo->execute(); // Run a count($files) test to make sure there are actually files; if so, proceed; if not, generate getErrors() if(!count($files)) { $contact_photo->error("Sorry, but you need to add a photo!"); return false; } // Do an initial save in the ProcessWire page tree; set the necessary information (template, parent, title, and name) $np = new Page(); // create new page object $np->template = $templates->get("contact_submission"); // set the template that applies to pages created from form submissions $np->parent = $pages->get("/customer-service/contact-us/contact-submission-listing/"); // set the parent for the page being created here // Send all the form's $_POST submissions through ProcessWire's sanitization and/or map to a variable with the same name as the template fields we'll be populating $np->title = $sanitizer->text($input->post->contactname); $np->name = $np->title; $np->contactname = $sanitizer->text($input->post->contactname); $np->email = $sanitizer->email($input->post->email); $np->comments = $sanitizer->textarea($input->post->comments); $np->save(); // Run photo upload foreach($files as $filename) { $pathname = $upload_path . $filename; $np->contact_photo->add($pathname); $np->message("Added file: $filename"); unlink($pathname); } // Save page again $np->save(); ?> <p>Thank you for your contact information.</p> <?php return true; } else { ?> <p> Sorry, your photo upload was not successful...</P> <?php } ?> Replace the field references with your own field names, make sure to change the various paths to match yours, and change the various messages to be what you need for your project. Read the entire discussion to see how we worked through getting to the solution shown above. Thanks, Matthew
  12. Hi folks, I'm scoping out a job and as part of the site they would like an 'Events' section. I have done quite a few of these which vary in complexities, but they are a client that has come from Wordpress and mentioned a 'Events Manager' plugin ( which they used mainly for the following: Allow online booking Create reports about attendees Send group reminders/confirmation I'm wondering if there's anything that ProcessWire can do that is similar? I guess, per event, the user would select a number of tickets, include their name and perhaps some other information, then it would store this in the admin area somewhere – perhaps a form connected to a specific event? Then they could export this data to see everyone who is attending etc? Group reminders/confirmation I'm unsure about but any help with this would be appreciated. Thanks! R
  13. Hi everyone! I'm building some Liferay portlets for a call center and I'm looking for form engines like Alpaca Forms which is the one I'm currently using (and fits my needs), but I would only like to ask around if someone knows of a similar alternative when it comes to generating forms on the front.
  14. We have a client with a site running ProcessWire. We have encountered some issues with a form a previous developer on our team made. Since we are extremely busy and need a helping hand, I am reaching out to the community. Essentially the form we had is an order form running on Form Builder. We chose form builder because of the ability to rapidly develop forms and store data. However we can move away from it for the order form. Basically here is what we need: An order form running on PHP or FormBuilder Form must output an order number and send an email to various emails with the order details. Also need an auto responder email with the order details and business information from the client. The order number must increment. Once the form is submitted, the results need to display on the same page with a print button. This form must work on all browsers! Need this built today or tomorrow. Will pay immediately and we will keep work coming your way if all works well. PM for the site details.
  15. Hello. I need to create a page select type of field in a frontend Form The form is created using API: $formJob = $modules->get("InputfieldForm"); $formJob->method = "post"; ... And each field is created and added to the main form Object using corresponding Inputfield(X) module $field = $modules->get("InputfieldText"); $field->placeholder='NAME'; $field->attr('id+name','name'); $field->required = 1; $field->maxlength = 150; $formJob->append($field); The question is: How can I use the PageAutocomplete module in my form? I have tried adding a field as in the previous example: $field = $this->modules->get("InputfieldPageAutocomplete"); And setting the corresponding variables. Even included some JS files from Core: wire/modules/JqueryCore/jqueryCore.js ,wire/modules/JqueryUI/JqueryUI.js and the module JS file itself. But nothing happens, no ajax call, no jquery UI initialization, nothing. It is possible to use this inputfield outside the admin area/backend? Any help is appreciated.
  16. Hello, I am building a dynamic frontend form from fields of a page, following Soma's great gist example. The form is working fine, except for multi language values. After this part of the code $form->processInput($this->input->post) when I loop over the form fields, I don't know how to access the multi language values of a field foreach($form as $field) { // how to get multi lang values here } What I tried is not working foreach($form as $field) { if($field->type instanceof FieldtypeLanguageInterface) { foreach ($languages as $lang) { $langval = $editpage->$field->getLanguageValue($lang); $editpage->$field->setLanguageValue($lang, $langval); } } else { $editpage->set($field->name, $field->value); } } Actually the $field->type returns just "text" for a PageTitleLanguage field. var_dumping the $field reveals that the language values are stored deep inside the object like 'value1023' => string 'Testworkshop2' (length=13) 'value1032' => string 'Testworkshop2 Englisch' (length=22) So how would I access those other than pulling them directly from $this->input->post?
  17. Hey guys, I'm trying to build a submit form with the ProcessWire API. After the form is submitted its data should be saved into different pages. I've followed Soma's great tutorial and wanted to improve it for my use case: Instead of adding every field manually to the form I already managed to automatically read out the fields that belong to a specific template like this: // Build form $form = $modules->get("InputfieldForm"); $form->action = "./"; $form->method = "post"; $form->attr("id+name",'$page->name'); // Build fieldset $fieldset = $modules->get('InputfieldFieldset'); $fieldset->label = 'Personal Data'; // Read out template fields and append them to the fieldset $registration = $templates->get("registration"); foreach ( $registration->fields as $field ) { $field = $field->getInputfield($page); $fieldset->append($field); } $form->append($fieldset); // more fieldsets... // Submit $submit = $modules->get("InputfieldSubmit"); $submit->attr("value","Anmelden"); $submit->attr("id+name","submit"); $form->append($submit); This seems to work great – with just one little restriction: Instead of the global field labels I would love to get the template specific settings for each field (defined within the template). E.g. in this template I'm using a body-Field not labeled as "Body" but as "Description". Same would be great for things like field's columnWidth, required properties and Co. Is this possible? Thanks a lot for your help! Nik
  18. Hi, is there actually a function in Processwire to create forms from a JSON array with corresponding attributes, so that something like { "title":"Duck Count", "type": "InputfieldInteger", "label": "How many ducks?" },{ etc ... } would become a form with all the fields? Otherwise it would be a nice-to-have I guess? I will give it a try for a module now - could be enhanced then. Or has anyone already build something like that? cheers, Steffen
  19. Is there a method to add markup to a single input field when building a form? At present I'd customise the forms markup: $form = $modules->get("InputfieldForm"); $form->setMarkup([ 'item_content' => "{out}<span class='custom-span'></span>", .... ]); Which works but adds the custom span to every inputFieldWrapper. Adjusting setMarkup on an individual field, i.e. $field = $modules->get("InputfieldText"); $field->setMarkup([ 'item_content' => "{out}<span class='different-span'></span>" ]); Calls the same method, setting $markup within inputFieldWrapper.php and adjusting the output of every inputFieldWrapper Therefore I was hoping for a way of appending to the inputfield or wrapper without it being global
  20. Hey all, I have just created a contact form with the PW api (nice and easy as expected, though I found it has some limitations concerning fieldsets and multi-row layout... I know this is a tricky subject, so no offense meant). I'm wondering what would be the best way to prevent the (accidental) resubmission of a form. I usually do this with a redirect after submit and a flash error/success message... is there any PW-ish way to achieve this (e.g., does PW support flash messages, or is this procedure even already implemented in the api somewhere)?
  21. Hello Experts, I am trying to make a quiz contest in processwire. This quiz needs to show one question per page. The aim of this quiz is to get more page views. so I created a template, where Quiz questions can be uploaded. After answering one question the user is redirected to the next question or URL on clicking the submit button. I am unable to get the form data. I have the form template and the final page to evaluate the scores. I dont understand where I am going wrong. Here is my code. Please help me out..... quiz.php <?php include("./"); include("./functions.php"); ?> <div id="content" class="row inside search-page"> <!-- content starts --> <div class="content-border"> <!-- content-border starts --> <div id="body" class="large-8 columns" role="content"> <!-- body starts --> <div class="large-12 columns"> <form id="form1" name="form1" method="post" action="../process-quiz" > <?php $name = 0; $arrlength1 = count($name); echo $arrlength1; for($x=0;$x<$arrlength1;$x++) { echo "<input type='hidden' name='answer[]' value='$name[$x]' />" ; } $p = $page->question; echo "<h1>Q:<span>{$p}</span></h1>"; if($page->quiz_images !=null) { $image = $page->quiz_images->url; echo "<img src='{$image}'>"; } foreach($page->quiz_options as $c) { echo "<input type='radio' name='answer[]' value=\"{$c->quiz_answer_text}\">{$c->quiz_answer_text}<br/>"; } ?> <input type="submit" name="button" id="button" value="Next" /> </form> </div> </div><!-- body ends --> <?php //include("./"); ?> </div><!-- content-border ends --> </div><!-- content ends --> <?php include("./"); ?> process-quiz.php <?php $name = $input->post['answer']; $arrlength=count($name); $myarray = array(); array_push($myarray, $name); $answers =array('one','right'); $score=0; foreach ($myarray as $innerArray) { // Check type if (is_array($innerArray)){ // Scan through inner loop foreach ($innerArray as $value) { //echo $value."<br />"; foreach($answers as $key) { if($value == $key) { $score++; } } } } } $url = "question-".$arrlength; if($arrlength>2) { $url="process-quiz.php"; } $session->redirect("$url",false); echo "<h1>you have scored :".$score."</h1>"; echo '<pre>'; // just to check the user inputs. print_r($myarray); echo '</pre>'; }?>
  22. TL;DR : I'm looking to create dynamic forms which will take fields list from given template & create/save pages dynamically. Hello, I've been using PW for a while for creating web applications like ERP systems and similar applications which have tons of forms. So far I've been creating, processing & validating them manually. While researching I found this link which I found to be very helpful. Code given in that example allows user to create a form based on the fields of any page and save it, which is very cool. Based on that code I tried doing something like this: $p = new Page(); $p->template = "mytemplate"; //I've added few fields to this template $p->parent = "/someparent/"; $p->of(false); // make a form $form = $modules->get('InputfieldForm'); $form->method = 'post'; $form->action = './'; // add the page's fields to the form $form->add($p->getInputfields()); // add a submit button to the form $submit = $modules->get('InputfieldSubmit'); $sumit->name = 'submit'; $form->add($submit); // process the form if it was submitted if($input->post->submit){ $form->processInput($input->post); $p->name = date(dmYhisn); $p->save(); } It did create a page but without any data. I know this could be a very stupid thing to try, but I guess it was worth it. More research taught me that probably using ProcessPageAdd module I can create new pages. But I don't know how exactly that works. I'm looking for some guidance about modules & their use on fron-end. Thanks.
  23. A company approached me wanting to convert their paper-based ways of collecting customer information into electronic. Reason being they want to instead use a tablet (in office) and have them fill out everything electronically in order to prevent readability / processing errors and also offer the ability to fill out on their website. The type of information such a company needs from their client is pretty intense and detailed. Customers are filling out multiple documents disclosing personal information, not only about themselves, but also about the defendant - everything from vehicle registration, address / work history to personal identity to the fullest extent) - things like social security numbers, etc. It seems there isn't a sensitive data question not being asked. Not only that but they are also disclosing credit card info (for payment). It's pretty monumental in terms of data. I never accepted the project and said I'll look into what's possible but out of curiosity and being the curious type I am, I have already built a mobile-responsive / electronic version of their entire 200+ question form(s), complete with task completion status, page summary, auto-complete, validation, terms of service. It's damn beautiful but that was the easy. Even though I like getting my feet wet, I am wondering if I should continue or if it's even worth the headaches, not to mention the technical hurdles. The questions I am wondering are numerous (and for understandable reasons). I guess the top would be: I know all this data has to be encrypted and secured to the highest extent. I don't know what's involved or how deep it can get. I do know the risks and the laws governing storage of such sensitive data and also the penalties for the company if it gets stolen. So I'm hesitant to even take on this task for that reason alone; especially since I'm still very much a PHP / programming beginner (although devoted). I don't want to major f*** up I was thinking storage would be on the web host instead of some sort of in-office database? An online back-end would have to be created to retrieve information so that the company then could process it (they wanted it as a pdf). They need some way to retrieve the data. They need to be able to charge / have access to the credit card again at a later date so integration with a payment processor needs to be implemented, correct? I am asking more what direction / route / study material I should look into (first steps) more than specific procedures because I understand it's very involved. If I can't tackle this now, I would like to learn so I can accomplish this in the future because building, integrating and deploying things of this nature is where I would like to go. Just curious on your thoughts. Thanks everyone
  24. As part of the Agile user story system that I'm in the process of building, each story has a list of acceptance tests that go with it. I have this list put together with a repeater, and I've added a checkbox to each test so that developers can mark it off as complete. What I really want to do, however, is not require developers to edit the page to check things off. They aren't writing the stories, only reading them, so I really want to find a way to give them a checkbox on the rendered page itself that can update the state of the checkbox field when they click it. The users viewing the page are already logged in (I'm using Adrian's Protected Mode module to lock down the whole site), so It seems like then first step will be to find the right Process API call to save a change to the page. The second step is probably harder, though, making all this happen from Javascript.
  25. Hi everybody, As much as we hate the CAPTCHA, it is still used. I decided to share my solution of using ProcessWire forms with CAPTCHA. My goals were quite simple: 1. Create a form and customize it. 2. Get an Inputfield for a page field and append this Inputfield to the form. 3. Display a CAPTCHA. 4. Process the form and check its fields for correctness. 5. Check the CAPTCHA. 6. If steps 4-5 fail, display the form back with the user input intact. What I found to be not quite easy was how to push a different CAPTCHA into an already submitted form. (A spoiler: this is done quite smoothly with the power of ProcessWire's Inputfields.) Let's start, then. My Form class has several methods: appendFields() accepts an array of field names, gets their Inputfields from a template and appends these to the form displayForm() adds a CAPTCHA and returns the form's HTML processForm() checks the CSRF session ID and user input and delegates CAPTCHA verification getCAPTCHA() returns the html for the CAPTCHA checkCAPTCHA() checks the user input against the CAPTCHA and sets the verification flag to true or false. That's mostly it. Now to the code itself. class Form { public $form; public $captchaVerificationResult; // captcha verification flag (bool) public function __construct () { // form is created upon class instantiation $form = wire('modules')->get("InputfieldForm"); $form->action = wire('page')->path; $form->method = 'post'; $form->attr("id+name", 'form'); $form->attr("class", 'pure form'); // I use PureCSS class name here as an example // how form items are displayed can be customized $form->setMarkup(array ( 'list' => "\n{out}\n", 'item' => "\n\t{out}\n\t", 'item_label' => "\n\t\t<label class='pure-form' for='{for}'>{out}</label>", 'item_content' => "\n\t{out}\n\t", 'item_error' => "\n<p><span class='ui-state-error'>{out}</span></p>", 'item_description' => "\n<p class='description'>{out}</p>", 'item_head' => "\n<h2>{out}</h2>", 'item_notes' => "\n<p class='notes'>{out}</p>", ) ); // form classes can also be customized $form->setClasses(array ( 'list' => 'Inputfields', 'list_clearfix' => 'ui-helper-clearfix', 'item' => '', 'item_required' => '', 'item_error' => 'ui-state-error InputfieldStateError', 'item_collapsed' => '', 'item_column_width' => '', 'item_column_width_first' => '', ) ); $this->form = $form; } public function appendFields ($fields) { /* * $fields is an array of field names * * for each field name a corresponding Inputfield is fetched from a page * and appended to the form * */ $page = wire('pages')->get("999999999"); // this is the page that has your fields foreach ($fields as $f_name) { $field = wire('fields')->get($f_name); $if = $field->getInputfield($page); // this page must have field name $f_name among its fields! $this->form->append($if); } /* * * CAPTCHA placeholder */ /* * create an InputfieldMarkup field, * give it an ID and append to the form * * Later this Inputfield can be easily found by its ID. * * */ $inputfield = new InputfieldMarkup; // inputfield markup is appendable to form! $inputfield->id = 'captcha1'; // id of the InputfieldMarkup with CAPTCHA $this->form->append($inputfield); /** * finally, the SUBMIT button * */ $submit = wire('modules')->get('InputfieldSubmit'); $submit->skipLabel = Inputfield::skipLabelBlank; // remove the label $submit->name = 'submit_save'; $submit->value = "Save"; $this->form->append($submit); } public function get () { return $this->form; } public function displayForm ($form) { /* * Each time the form is displayed, the CAPTCHA should be there * * So, behore doing $form->render() let's get an InputFieldMarkup field by ID * and pour some fresh CAPTCHA in it * * */ $form->children->findOne("id=captcha1")->value .= $this->getCAPTCHA(); return $form->render(); } public function processForm ($form) { try { $form->processInput(wire('input')->post); wire('session')->CSRF->validate(); } catch (WireCSRFException $e) { die ($this->displayForm($form)); } $this->checkCAPTCHA(); // sets class property $captcha_verification_result to false/true if (!$this->captcha_verification_result) { $form->children->findOne("id=captcha1")->value = "Wrong captcha, try again <br />"; // this will go before the CAPTCHA code die($this->displayForm($form)); } else { // let's do some simple checks // you can and should do more of yours, of course $email = $form->get("b_email"); if (filter_var($email->value, FILTER_VALIDATE_EMAIL)) { $email->error = "Incorrect email format"; } if ($form->getErrors()) { // the form contains errors, display it with user input die($this->displayForm($form)); } else { echo "Thanks for the submission!"; // everything is just right } } } public function getCAPTCHA () { /* * * $captcha_html = your CAPTCHA code * */ return $captcha_html; // have a lovely CAPTCHA } public function checkCAPTCHA () { /* * * get some response and check it * * */ if ($response->failed) { $this->captchaVerificationResult = false; } else { $this->captchaVerificationResult = true; } } } Here's how this can be used: $form = new Form(); $formFields = array ("name", "email"); $form->appendFields($formFields); $newForm = $form->get(); if ($input->post->submit_save) { // user submitted the form, process it and check for errors $form->processForm($newForm); // the form was processed successfully because nothing die()'d. Now it's time to play with what's been submitted. } else { echo $form->displayForm($newForm); // if it's not been submitted, just display it and the CAPTCHA } With this being just a generic idea on how to do form processing with CAPTCHA, I hope portions of this code will prove helpful in your development. Your comments, corrections and suggestions are very much welcome.