Jump to content

Create simple forms using API


Soma

Recommended Posts

Don't Show API Form Labels 

(If I may add this here for the sake of completeness.)

I have been looking for a way to leave the label out of the markup that does not involve recreating a module (a silly thing to do). The solution we have been using up until this point was a blank label. (Resulting in unnecessary markup and a negative margin.) However curiosity took me to the Inputfield module. Hey great job on these fields BTW. Reading the file I came across these options.

const skipLabelNo = false; // don't skip the label at all (default)
const skipLabelFor = true; // don't use a 'for' attribute with the <label>
const skipLabelHeader = 2; // don't use a ui-widget-header label at all
const skipLabelBlank = 4; // skip the label only when blank

// wire/core/Inputfield.php

Found in: in Inputfield.php 

The best solution I found to use this in a form builder. (I would like to credit this to somma's comment on checkbox-other-text-in-header-than-label-text)

//controller.php
$submit = $modules->get("InputfieldSubmit");
$submit->skipLabel = Inputfield::skipLabelBlank; //HERE IS THE SOLUTION!
$submit->attr("value","SUBMIT");
$submit->attr("id+name","submit");
$submit->attr("class","button");
$form->append($form_submit);

Thank you Somma!

Thank you Ryan!

  • Like 10
Link to comment
Share on other sites

  • 4 weeks later...

HowTo: InputfieldWrapper classes (Question)

Adding classes to the wrapper via a hook.

So here I am again. Wrestling with the API form. Love it and know I don't know enough to say anything bad about it. I am certain that there is a way to do most things you want when using the Processwire API. 

Short Description

What I am trying to achieve is have all the Inputfields in my form render with unique classes. Why I am trying to do this is I am using a CSS-Framework that has an insanely intuitive grid system and would like to use these classes in the form. So when at render I will output the classes specific to that field. Hooking is one way I have thought of that might be plausible but, as mentioned I don't know how best to do it due to my limited knowledge of ProcessWire. I am open to other suggestions too.

Method

Create a form as in the feed done like Soma has suggested. Add to the form a markup and class array. Now add the fields you desire. In short...

<?php /* contact_contoller.php */
// And a whole lot more code
function hookAppendClassName($event) {
  $otherEvent = $event->arguments(0); // grab event provided to PageRender::renderPage
  $className = " [classes for the grid]";
  $classes_array = $otherEvent->object->getParent()->getClasses();
  $classes_array = array_merge($classes_array, array('item' => $classes_array['item']." ".$className));
  $otherEvent->object->getParent()->setClasses($classes_array);
  $otherEvent->return = $event;
  $event->replace = true;
}
function createForm() {
  $form = $modules->get("InputfieldForm");
  $form->setMarkup(array(
    'list' => "<div {attrs}>{out}</div>",
    'item' => "<div {attrs}>{out}</div>",
    'item_label' => "<label for='{for}'>{out}</label>",
    'item_content' => "{out}",
    'item_error' => "<p>{out}</p>",
    'item_description' => "<p>{out}</p>",
    'item_head' => "<h2>{out}</h2>",
    'item_notes' => "<p class='notes'>{out}</p>",
  ));

  $form->setClasses(array(
    'list' => '[list-class]',
    'list_clearfix' => '',
    'item' => '{class}',
    'item_required' => '',
    'item_error' => '',
    'item_collapsed' => '',
    'item_column_width' => '',
    'item_column_width_first' => ''
  ));

  $form_name = $modules->get("InputfieldText");
  $form_name->addHookBefore('renderValue', $this, 'hookAppendClassName');
  $form_name->label = "Name";
  $form_name->setParent($form);
  $form_name->required = 1;
  $form_name->attr('id+name','name');
  $form_name->attr('placeholder','Name');
  $form_name->attr('class','');
  $form->append($form_name);
}

This code does not work. Was hoping someone could be of assistance. Here is my current output.

<html>
<form id="contact-form" class="InputfieldForm" name="contact-form" method="post" action="./" data-colspacing="1">
  <div class="[list-class]">
    <div class="InputfieldText" id="wrap_name">
      <label for="name">Name</label>
      <input id="name" class="InputfieldMaxWidth" name="name" type="text" maxlength="2048" placeholder="Name">
    </div>
  </div>
</form>
</html>

This is what i desire. Note the [list-class__item].

<form id="contact-form" class="InputfieldForm" name="contact-form" method="post" action="./" data-colspacing="1">
  <div class="[list-class]">
    <div class="InputfieldText [list-class__item]" id="wrap_name">
      <label for="name">Name</label>
      <input id="name" class="InputfieldMaxWidth" name="name" type="text" maxlength="2048" placeholder="Name">
    </div>
  </div>
</form>

Thanks in advance!

Link to comment
Share on other sites

Your hook and method has a lot wrong.

If this all would work, then you would hook into Inputfield::render() and not Inputfield::renderValue();

And a hook to do what you wanted would look more like this:

function hookAppendClassName($event) {
  $className = " mygrid";
  $classes_array = $event->object->getParent()->getClasses();
  $classes_array = array_merge($classes_array, array('item' => $classes_array['item']." ".$className));
  $event->object->getParent()->setClasses($classes_array);
}

But this is not possible. When a inputfield is rendered in the inputfieldwrapper, the classes and markup is already set and you can not overwrite it at that moment in time.

I also was looking into this and by chance I found a line of code in latest dev, that seems to be added recently. InputfieldWrapper rendering method looks for a $inputfield->wrapClass, I didn't know was there.

So you can now simply do this:

$field = $modules->InputfieldText;
$field->label = "Name";
$field->wrapClass = "mysuperlol-col1--wonder__toootooo";
...
  • Like 6
Link to comment
Share on other sites

Thanks Soma

Thanks Soma. That should work. Busy downloading Processwire from Github now. I see my mistakes now. I had it correctly but changed it to the wrong code and did not fully correct it when I uploaded the code. Sorry about that renderValue.

The only issue I have with this method is that it comes from the dev branch. Production should be kept separate from dev in my opinion.

Link to comment
Share on other sites

I'm trying to get a image upload working with the form api. 

	$field = $modules->get("InputfieldImage");
	$field->attr('id+name','images');
	$field->required = 0;
	$field->destinationPath = $config->uploadTmpDir;
	$field->extensions = "jpg jpeg gif png";
	$field->maxFilesize = 2*1024*1024;
	$field->maxFiles = 1;
	$field->skipLabel = Inputfield::skipLabelBlank;
	$form->append($field);

But if I call 

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

I get this error: 

Error: Exception: Nicht zulässiges Bild (in /Users/Benni/Projekte/A-06-2014_HONourables/www2/wire/modules/Inputfield/InputfieldFile/InputfieldFile.module line 282)

or with InputfieldFile

Error: Exception: New page '/mitglieder/postfach/conversation-2014-09-06-10-59/' must be saved before files can be accessed from it (in /Users/Benni/Projekte/A-06-2014_HONourables/www2/wire/core/PagefilesManager.php line 240)

I don't understand why this is trying to create a page in this location, which is the location of the page, which shows the form. The file is supposed to be for a page further down the hierarchy. Also the only template allowed as child of "postfach" doesn't even have a image field which could serve as temporary storage. 

I could use own upload processing, but I would much rather stay consistent with the form api.

  • Like 1
Link to comment
Share on other sites

@lostkobrakai, you many read this thread again as this has come up multiple times (not only in this thread) from around here https://processwire.com/talk/topic/2089-create-simple-forms-using-api/page-5 or just scan the whole thread as it's full of this. There's also some gist examples https://gist.github.com/somatonic/5236008

Link to comment
Share on other sites

I try to generate a form from a (multidimensional) array and searching for the best data format... any suggestions?

It have to map 

1) form / field values

$form->method = 'post';
$form->set('method', 'post'); // should work to?

2) form / field attributes

$form->attr('id+name', 'myForm');

3) defined Inputfield type like

InputfieldText
InputfieldSubmit
...

First array format is something like this...

$formField = array('module' => 'InputfieldText', 
                   'attr' => array('key' => 'value'),
                   'set' => array('key' => 'value'));

So I can cutting attributes, ...

But it looks... confusing *g*

*UPDATE*

But could be parsed with a function like that (untested)...

    protected function createFormFields() {
        foreach ($this->option['formFields'] as $formField) {
            $field = $this->modules->get($formField['module']);            
            
            foreach ($formField['set'] as $key => $values) {
                $field->set($key, $value);
            }
            foreach ($formField['attr'] as $key => $values) {
                $field->attr($key, $value);
            }
            $inputfields[$field->name] = $field;
        }
        return $inputfields;
    }

$this->option['formFields'] is a multidimensional array with the form data / config...

Link to comment
Share on other sites

tried to remove all classes from Inputfield and set one single new class. Expected class="loggy" get class="loggy InputfieldMaxWidth". Why? Which method will remove all classes persistent?
 

	$form = $modules->get('ProcessLogin');
	$form->addHookAfter('buildLoginForm',null, function ($event) {
		$new = $event->return;
		$new->get('login_pass')->removeAttr('class'); // removes: class="whatever"
		$new->get('login_pass')->setAttribute('class','loggy');// adds: class="loggy InputfieldMaxWidth" and not class="loggy"
		$event->return = $new;
	});
	echo $form->execute();

Link to comment
Share on other sites

  • 2 months later...
  • 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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...