Module want: form builder
#1
Posted 28 January 2011 - 05:08 PM
Easy to use, most basic fields only (text input, textarea, email etc) at first.
Any thoughts how this should be done?
#2
Posted 28 January 2011 - 05:22 PM
Next: I think we could do this the very same way templates are done: Fields have their definitions and their 'administration-form-look', ui. If we add 'simple-form' and 'validation-rules' for this, we can actually reuse the very same fields we use in templates [or better yet, the very same types of fields].
This idea is just created: I wasn't thinking about any implications, just think about this process:
- 1 – add new 'form-template'
- 2 – define fields
- 3 – define 'action' php file
- 4 – include some tag or php code [tag is here better, because you may need to add this into wysiwyg]
Then in the 'action' file you can have these pseudo-functions [ideas of priceless functions:]
<?php
//note: baic validation rules [required, e-mail, etc.] were defined in editor
//note: also you checked 'sanitize' for fields you want have sanitized, so they are already
$form->addValidationRule( /*description here*/ );
$form->addValidationRule( '{x} + {y} >= 40' ); //some math validation rules?
$form->addValidationRule( /* another one */ );
if ($form->validate){
$mail = new Mail();
$db_do = new DBRecord();
$form->redirect_after = '/page/url';
}
Note: if no 'redirect_after' found, system returns to 'form' page. Show errors routine if not validate can be automated: just go back to form and show errors.
Note 2: As I see it, this is close to 0, if we talk about how much is done. But outlined model of form editor is very close to whole idea of PW – does the tedious stuff for you without taking away any freedom [anything you might need to customize – HTML, CSS – it's just not shown here, but we'll think it through]
After longer thinking, we might come with all posiible outcomes of forms – there isn't much really – you either show message 'ok', go to 'thank you' page or go to another step [if multiple forms]. There isn't anything in between.
#3
Posted 28 January 2011 - 05:26 PM
Edit: I see Adam is thinking the same thing (and typing at the same time as me).
#4
Posted 28 January 2011 - 05:35 PM
The last sentence was re: send mail/save into db action if everything's ok – I think we might not automatize this part – just give the authors really good API to use pages, DB & send mails at first.
Then, in the second part [when PW will be a little more user-centric (I think we are now 'web people – centric' ;D)], we can add some default editable actions and leave the advanced stuff optional.
#5
Posted 28 January 2011 - 05:41 PM
I have to build a contact form for a site that's going up tomorrow and think I'm going to use the Inputfield modules to do it (manually) just to see how it might work. I'll post the template and result here tomorrow if you guys want to see it. I think it'll lead to some more thoughts on a form builder.
#6
Posted 28 January 2011 - 06:18 PM
My two cents
- Default markup is needed here, it should be plug and play
- Of course it would be nice to have full control of markup when needed
- As Ryan said, template editor is actually form building (we define fields, admin site shows form for us). I think that the UI with current template editor is easy enough for non-technical content editors - so we should use that as much as possible
Very interesting to see your findings Ryan about using Inputfield modules to create front end forms.
#7
Posted 29 January 2011 - 01:22 AM
#8
Posted 29 January 2011 - 03:24 PM
This is just a start on this module... lots more to cover obviously, but just wanted to get the momentum going. And it is fully functional even in this state, if anyone wants to try it out. I just experimented with simple forms having "name, email and message" text fields, so far.
Here are usage instructions below (pulled from the module file), and the .module file is attached if anyone wants to try it or work with it. Just place it in: /site/modules/FormTemplateProcessor.module
/**
* Module to let you use templates as web contact forms.
*
* Can send you email and/or save the submission to a page in your site.
*
* Usage:
*
* 1. In admin, create the fields you want to be part of the form.
* 2. Create a new template and assign your fields to this template.
* 3. Create another template for your contact form page (if you don't already have one).
* 4. Use the example below as a starting point for this contact form page:
*
* $form = $modules->get('FormTemplateProcessor');
* $form->template = $templates->get('my_contact_form_template'); // required
* $form->requiredFields = array('fullname', 'email');
* $form->email = 'your@email.com'; // optional, sends form as email
* $form->parent = $page; // optional, saves form as page
* echo $form->render(); // draw form or process submitted form
*
* 5. Use CSS to style the fields. See the bottom of this file for suggestions.
*
*/
Download at GitHub:
https://github.com/r...mplateProcessor
#9
Posted 29 January 2011 - 03:55 PM
Tested it quickly: got this error
Call to undefined method stdClass::render() (line 19 of C:\apache\htdocs\pw\site\templates\page.php)
This is what I have on template file:
$form = $modules->get('FormTemplateProcessor');
$form->template = $templates->get('contact_form'); // required
$form->requiredFields = array('title');
$form->parent = $page; // optional, saves form as page
echo $form->render(); // draw form or process submitted form
I have template called contact_form, which has only two fields (title & body).
There might also be typo on your example: last $form is $contactForm
#10
Posted 29 January 2011 - 06:12 PM
#11
Posted 29 January 2011 - 06:33 PM
#13
Posted 29 January 2011 - 07:06 PM
#16
Posted 11 February 2011 - 10:26 AM
The purpose of Inputfields is to generate markup for inputs (and retrieve the resulting value). This is why they are separate from Fieldtypes. Since they were originally built just for the PW Admin use, I haven't made them configurable from a markup aspect. Though I do plan to change that, now that the utility of these Inputfields is expanding.
Currently, there is only one markup generation method in most Inputfields, and that is the ___render() method. So you can extend any Inputfield, and just override the ___render() method to change the markup it generates. But I'm guessing it's not the actual Inputfields that you want to override so much as the container code generated by the InputfieldWrapper class (with it's jquery-ui classes and list items and stuff). The reason I say that is because the Inputfield types just generate the actual form inputs, like an <input ...> tag. Whereas InputfieldWrapper generates everything else.
Until I can modify this class to make it's markup configurable, I would recommend styling the existing markup using the CSS classes in the comments at the bottom of the .module file as a starting point.
But I think it will be relatively easy for me to make the InputfieldWrapper class have configurable markup, so it's something I can do quickly if you are interested. But I want to make sure that I'm understanding your needs correctly before I do that. If you just need to modify a single Inputfield's output or something, then we'll focus on that instead.
#17
Posted 11 February 2011 - 11:04 AM
I have updated my CSS to use what you have to start and it works well. I mainly use site templates built by external designers for my work, so many times it's easier to just render forms like the designer's examples and have them work and function great. This way I don't have to spend a ton of time updating their css, js, etc.
What I would like to do is be able to override the wrapper class within a template rather than creating a new module to override the wrapper.
Maybe something like: (from your module...I have just changed it a bit so it's not a contact form anymore)
<?php
// get the collection of inputs that can populate this page's fields
$inputfields = $page->getInputfields();
// set values for fields and add them to the form.
foreach($inputfields as $inputfield) {
if ($inputfield->name == 'title') continue;
// populate values
if ($page->name != 'create') {
$inputfield_name = $inputfield->name;
$inputfield->value = $this->page->$inputfield_name;
}
// *****Maybe some markup here?*****
$inputfield->markup("./markup/{$inputfield->type}");
if(in_array($inputfield->name, $required_fields)) $inputfield->required = true;
$form->add($inputfield);
}
Just a thought
-Jim
#18
Posted 01 May 2011 - 06:53 AM
What I would like to achieve is something where I could just say that "render form for that $page and process it when it is submitted". It would then use all the inputfields that are set to those fields (like AsmSelect, radio etc). And I think sometimes I would need to process forms by myself so that is not requirement. But ability to easily render forms and their input "widgets" is what I need.
I tried to figure out how the things work from current admin, but got confused at some point (I am pretty new to oo programming).
#19
Posted 01 May 2011 - 08:05 AM
<?php
$form = $this->modules->get('InputfieldForm');
$fields = $somepage->getInputfields();
$form->append($fields);
echo $form->render();
I have added these lines to head:
<?php foreach($config->styles->unique() as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; ?> <?php foreach($config->scripts->unique() as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; ?>
But only thing that gets included are JQueryFancyBox.css & .js, I have images field, AsmSelect etc.
#20
Posted 01 May 2011 - 11:08 AM
When it comes time to process the form, you can do this:
<?php
if($input->post->submit_save) {
// replace 'submit_save' (above) with the name of your 'save' button field name.
// tell the form to process input from the POST vars, $input->post:
$form->processInput($input->post);
}
If you want to check if there were any errors (after calling processInput above):
<?php
$errors = $form->getErrors();
if(count($errors)) {
// $errors is an array of strings with error messages
// each Inputfield also highlights it's own errors the next time you call render()
}
Here's how you can retrieve the values from any given field:
<?php
$inputfield = $form->get('your_field_name');
$value = $inputfield->value;
// or a shorter version of the same thing:
$value = $form->your_field_name->value;
You can also iterate the form:
<?php
foreach($form as $inputfield) {
echo "<li>{$inputfield->name} = " . htmlentities($inputfield->value);
}
The only thing to note about iterating the form is that some form fields contain more fields within them. You can identify them by the type:
<?php
if($inputfield instanceof InputfieldWrapper) {
// field contains more fields
}
So to process a form for a page, you might want to use a recursive function like this:
<?php
function populatePage($page, $inputfield) {
if($inputfield instanceof InputfieldWrapper) {
foreach($inputfield as $i) populatePage($page, $i);
} else {
// set the value to the page
$page->set($inputfield->name, $inputfield->value);
// optionally perform additional validation on the $inputfield->value before setting it
}
}
$form->processInput($input->post);
populatePage($page, $form);
Another approach for the same thing is to iterate $input->post, which puts them in a flat (non-recursive) context. But in this strategy, you have to do more validation to make sure the submitted fields are ones you intend to populate:
<?php
$form->processInput($input->post);
foreach($input->post as $key => $unused) {
$inputfield = $form->get($key);
if(!$inputfield || !$inputfield instanceof Inputfield) continue;
if(!$page->fields->has($inputfield->name)) continue;
// optionally perform additional validation here
$page->set($inputfield->name, $inputfield->value);
}
You can of course retrieve your values directly from $input->post (or $_POST), but the advantage of retrieving it from the $inputfield->value is that many inputfields perform some basic validation on the values you set to them.
In addition, every time you set a value to a page, it passes through the related Fieldtype's sanitize() method. That means that all values set to a page are converted to the right type for the Page. For example, a string submitted for a file in the POST vars is converted to a Pagefile object when you call $page->set($key, $value)... that in turn calls the Fieldtype's sanitize() method. This all happens behind the scenes.
An important thing to note is that these Fieldtype sanitize() methods are there to sanitize for type, not security. That Fieldtype::sanitize method doesn't know if it's being provided submitted input, or something that you just set to the $page from the API, or something loaded from the DB. So the sanitize method for FieldtypePage (as an example) will ensure that whatever gets sent to it is a Page or something that it can convert to a Page (like a string or array of strings representing pages). Whereas something like FieldtypeText will accept any text you provide to it... after all, a <script> tag may be a very legitimate thing in your text field. But a <script> tag can also be a very dangerous thing in another situation. So if you are using Inputfields outside of an administrative context, or in a context where you want to enforce specific values, you may want to perform additional validation according to your need. The PW admin doesn't need additional validation, but your own forms may.
Here's an example of validating a field for specific needs before setting it to a page. In this case, we know that in our field 'message' we just want plain text and no markup, and we want to limit the length to 500 characters. In our 'message' field settings, we have the "encode entities" output filter turned on, so we are not encoding entities as part of the validation.
<?php
$inputfield = $form->get("message");
$value = strip_tags(trim($inputfield->value));
if(strlen($value) > 500) {
$value = substr($value, 0, 500);
$inputfield->error("Truncated length of this field to 500 characters");
}
$page->set('message', $value);
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users













