Soma

Create simple forms using API

Recommended Posts

The error says exactly what you have to do: Save the page before files can be accessed...

But i don't want to create it before the submission. Because if i do this every visit of that form a new page must be created.

Is there a way to avoid this :

// We must have the Inputfield instance, not the Field.
$form->append($field->getInputField($curriculum));

I think if i create the form with the Inputfields from the instance of $curriculum, PW related this form to the object page (not yet saved), and of course throws that error when submitting.

Share this post


Link to post
Share on other sites

Soma,

Much appreciated. The *hash* thing threw me at first—but as usual—it's not that complicated.

What you posted was almost it, but it threw some error about using wire $input as an array.

I tweaked a little, and ended up with this (which works perfectly)

foreach($p->files as $file) {
    $id = "delete_files_". $file->hash;
    if(isset($input->post->$id)) { 
        $p->files->delete($file);
    }
}

Thanks again.

  • Like 2

Share this post


Link to post
Share on other sites

Alessio,

I see you have 

$curriculum = new Page();
$curriculum->template = "curriculum";
outside of  
if($input->post->submit)

Could there be an issue there?

Also, can you get the new page to save without fields?

Share this post


Link to post
Share on other sites

Alessio,

I see you have 

$curriculum = new Page();
$curriculum->template = "curriculum";
outside of  
if($input->post->submit)

Could there be an issue there?

Also, can you get the new page to save without fields?

I'm costrained to do this because the function "$field->getInputField($curriculum)" necessary takes an instance of Page to retrive the Inputfield associated.

Share this post


Link to post
Share on other sites

But i don't want to create it before the submission. Because if i do this every visit of that form a new page must be created.

Is there a way to avoid this :

// We must have the Inputfield instance, not the Field.
$form->append($field->getInputField($curriculum));

I think if i create the form with the Inputfields from the instance of $curriculum, PW related this form to the object page (not yet saved), and of course throws that error when submitting.

No there's no way to avoid this, except if you would do 

$fields = $somepage->fieldgroup;
foreach($fields as $f) {
    $inputfield = $fields->get("$f->name")->getInputfield($somepage);
    $form->add($inputfield);
}

This somehow gets around the error when rendering the form. But once submitted you'll end with the same error.

Yes you are correct. In PW a page needs to be saved before files can be added or accessed, the PagefileManager requires a page id and since you build it using inputfields in context of a page object it fails. Pagefiles are saved in the filesystem using the page id, and since the page doesn't yet have an id it's simply not possible. For the same reason Ryan's FormTemplateProcessor also only works with text fields.

Since you seem to have file fields in your template, you have to save the page to go this route, which I'm sure you don't want. Or remove file fields from the form, which is maybe also not what you want. So you have to build it different and build the form differently, maybe still using the fields from a template, but add your own file field upload. There various threads and example I did a while back. Some are on my gists. Example: https://gist.github.com/somatonic/4150974

  • Like 3

Share this post


Link to post
Share on other sites

What's the best way to achieve something like that:  

   $field->set("class" , "myclass");

Regards.

Share this post


Link to post
Share on other sites

 $field->attr("class" , "myclass");

Share this post


Link to post
Share on other sites

This will overwrite also existing classes. If you want them to stay

$field->attr("class" , $field->attr("class") . "myclass");

  • Like 2

Share this post


Link to post
Share on other sites

I have tried that from your example:

// create a text input
$field = $modules->get("InputfieldText");
$field->label = "Name";
$field->attr('id+name','name');
$field->label = "Name";
$field->attr("class" , "myclass");
$field->required = 1;
$form->append($field); // append the field to the form

but I get that:

<li class='Inputfield InputfieldText Inputfield_name ui-widget InputfieldStateRequired' id='wrap_name'>

	<label class='ui-widget-header' for='name'>Name</label>
	<div class='ui-widget-content'>

	<input id="name" class="required InputfieldMaxWidth" name="name" type="text" maxlength="2048" />
	</div>
</li>

myclass doesn't appear.

Share this post


Link to post
Share on other sites

I have tried that from your example:

// create a text input
$field = $modules->get("InputfieldText");
$field->label = "Name";
$field->attr('id+name','name');
$field->label = "Name";
$field->attr("class" , "myclass");
$field->required = 1;
$form->append($field); // append the field to the form

should be

// create a text input
$field = $modules->get("InputfieldText");
$field->label = "Name";
$field->attr('id+name','name');
$field->required = 1;
$field->attr("class" , $field->attr("class") . " myclass");
$form->append($field); // append the field to the form

required also adds a class...

Happy experimenting. :)

  • Like 3

Share this post


Link to post
Share on other sites

Awesome Soma, it opens the door to many things, I'm really happy with that!.

Share this post


Link to post
Share on other sites

Need a hint on where to start to render the form manually, without using $form->render();

Any advice?

Regards.

Share this post


Link to post
Share on other sites

Not sure I can follow. But yesno, if you use form inputfield then thats what you usually want to use as a whole. On the other hand you can render any inputfield individually but you have to do a lot more work and maybe manually creating the form would be also a good alternative. Just saying.

So why?

Share this post


Link to post
Share on other sites

I know you have a lot of experience templating, but I use bootstrap templates so I know the pages will render on most browsers and phones without much effort.

I got formbuilder but when I want certain output with my own classes names, spans, etc, I get lost, not able to do what I want; is because I  think rendering my self will give me more flexibility.

As an example the following page renders in mobile phones but I used formbuilder for the contact form and I can't get the results I want, if you see it on a desktop computer is ok but the columns in a mobile are to narrow, I attach a couple images for you to see the results.

By the way formbuilder is an incredible useful tool.

post-1191-0-57056200-1373307331_thumb.pn

post-1191-0-17648800-1373307338_thumb.pn

Share this post


Link to post
Share on other sites

maybe a custom coded form that could use formbuilder to process the submissions?

i suppose you could just copy the code that formbuilder generates and put in your classes...

another useful thing you can do with formbuilder is create a jquery-ui.js and main.js files, so you can use different js libraries (validators, custom time pickers etc.)..

  • Like 1

Share this post


Link to post
Share on other sites

Thank you Macrura these are three good ideas.

I've seen your form in ohmspeaker, it looks perfect, clean, usable, which aproach did you take?,

  1.- custom code.

  2.- copy formbuilder generated code.

  3.- create own  jquery-ui.js...

(Note. I'm enjoying fengoffice, thanks for the advice) 

Share this post


Link to post
Share on other sites

Hi Manol - the search form is just based off the skyscrapers profile, so all the answers are in there...

formbuilder not really necessary for something like that

Share this post


Link to post
Share on other sites

I would try to work as much with what PW gives you and adapt the CSS, I think there's even an responsive theme in Formbuilder... but could be wrong.

If you really need to adapt the HTML markup and CSS classes used by the InputfieldWrapper you can.

As in this thread already mentioned: from the InputfieldWrapper.php core class

    /**
     * Markup used during the render() method - customize with InputfieldWrapper::setMarkup($array)
     *
     */
static protected $defaultMarkup = array(
    'list' => "\n<ul {attrs}>\n{out}\n</ul>\n",
    'item' => "\n\t<li {attrs}>\n{out}\n\t</li>", 
    'item_label' => "\n\t\t<label class='ui-widget-header' for='{for}'>{out}</label>", 
    'item_content' => "\n\t\t<div class='ui-widget-content'>\n{out}\n\t\t</div>", 
    '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>",
    );

Using the form inputfield object you could simply

$form->setMarkup(array('list' => "<div {attrs}>{out}</div>"));

The same exists for the classes used. But at the end I don't know if messing with it helps.

Rendering form fields:

As I said earlier, it's always possible to render a certain field explicit. 

echo $form->get("name")->render();

You could even use the form building method in this thread starting post and render fields where you like. There'll be still markup being outputed depending on the inputfieldtype, but maybe allows for more flexibility.

$showform = true;

$form = $modules->get("InputfieldForm");

$field = $modules->get("InputfieldEmail");
$field->attr("name", "email");
$field->label = "Email";

$form->append($field);

if($input->post->submit) $form->processInput($input->post);

if($form->getErrors()) {
    $showform = true;
} else {
    $showform = false;
   // form valid, do something
}

if($showform) {
  echo "<form action='#' method='post'>";
  echo "<div class='row'>" . $form->get('email')->render() . "<div>";
  ...
}

Anything is possible, just use what you need. Think it's almost same as you would work with fields or pages. 

  • Like 6

Share this post


Link to post
Share on other sites

Thanks for this post, it has been really helpful!

Is there anyway to use HTML in the $field->description? 

Also, I think that I looked through all the posts and couldn't find anything, is there a way to choose a default selected option for InputfieldSelect?

Share this post


Link to post
Share on other sites

Hi kyle, 

The below code should do it (not tested, just wrote it in the browser)

Markup:

$html = "<h3>Condimentum Purus</h3><p>Cras Sollicitudin Vulputate Nullam</p>";
$markup = $modules->get("InputfieldMarkup");
​$markup->set("label", "Label for this");
$markup->set("value", $html);

Default selected:

$needed = "ProcessWire";

$array = array(
	array( "cms" => "Joomla", "value" => "If you don't mind code" ),
	array( "cms" => "modx", "value" => "Good for trouble shooters." ),
	array( "cms" => "ProcessWire", "value" => "Great, we selected this." ),
	);

$select = $modules->get('InputfieldSelect');

foreach($array as $option){
	$attr = $needed == $option['cms'] ? array('selected' => 'selected') : null;
	$select->addOption($option['cms'], $option['value'], $attr);
}
  • Like 4

Share this post


Link to post
Share on other sites

The more simpler and direct way for a custom select would be:

$sel = $modules->get("InputfieldSelect");
$sel->attr("name", "cms");
$sel->addOptions(array(
            'pw'        => 'ProcessWire',
            'joomla'    => 'Joomla!',
            'wp'        => 'Wordpress'
       ));

// setting the value will select the option, here with coming either from post or the default
$sel->attr("value", $input->post->cms ? $input->post->cms : 'pw');

echo $sel->render();
  • Like 4

Share this post


Link to post
Share on other sites

What is the best way to create a file input field to allow a visitor to submit a document that gets emailed on a successful form submission?  This is my code right now, but after the submission (successful or not) it reads no file chosen.

//create upload field
$field = $modules->get("InputfieldFile");
$field->label = " ";
$field->description = "Upload your plan.  File type must be doc, docx, or pdf.";
$field->required = 1;
$field->id = "file";
$field->name = "file";
$field->maxFiles = 1;
$field->maxFileSize = 1024 * 10;
$field->destinationPath = "/tmp/";
$field->extension = "pdf doc docx";
$form->append($field);

The tmp folder is located in the root of the site (where the site and wire folders are), and I thought it may have been a permissions issue, but it still reads no file uploaded even after I did chmod 777. 

Share this post


Link to post
Share on other sites
What is the best way to create a file input field to allow a visitor to submit a document that gets emailed on a successful form submission?  This is my code right now, but after the submission (successful or not) it reads no file chosen.

There are a lot of big security considerations with forms that accept files, and what happens to those files afterwards. The scope of it is a bit beyond what I think most would want to implement and monitor for a front-end form. As a result, I recommend using something existing that can do it safely, like ProcessWire Form Builder, or an external service like WuFoo. 

Share this post


Link to post
Share on other sites

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

  • Recently Browsing   0 members

    No registered users viewing this page.