Jump to content

Modify form object


pwFoo
 Share

Recommended Posts

Is it possible to replace / modify form fields after added to the form object?

$form->add($field);

Something like get the field from form, modify and replace it?

Or is there an example how to add after / before a form field? Is the form object (as object) or the object field name needed to replace it?

Link to comment
Share on other sites

Thanks Soma. 

$a->$key = $item
$a->set($key, $item)

$a->insertBefore($item, $existingItem)
$a->insertAfter($item, $existingItem)

$a->replace($itemA, $itemB)

$a->add($item)
$a->remove($item)

No problem with get a form field, but I have doubts about set / overwrite it ;)

So that should work?

// Get an added form field
$field = $form->get('myField');

// Do some changes to the field object...

// overwrite the "old" field object
$form->set('myField', $field);

// render the modified form...

@kongondo

Also thanks to you. Searched about wireArrays during my post and so posted after you *g*

Link to comment
Share on other sites

So $item, $itemA, $itemB and $existingItem could be a field object or simply a field name...?

$a->insertBefore($item, $existingItem);
$a->insertAfter($item, $existingItem);

$a->replace($itemA, $itemB);

Update

ok... it was to simple to believe it *g*

insertBefore, insertAfter works fine...

$existingItem = $form->get('myField')

Need some more testing with replace... Doesn't work at first tests...

Update2

Instead of replace (seems not work with forms) it could be done with two steps...

$form->insertBefore($myField, $form->get('myFormField');
$form->remove($form->get('myFormField'));
Edited by pwFoo
Link to comment
Share on other sites

Ah sorry, a form object is a InputfieldWrapper which is a special Inputfield, but it has Inputfields that are part of the InputfieldArray (defined at top of /wire/core/InputfieldWrapper). That's why replace(a,b) is not there for a form object.

So that should work?

// Get an added form field
$field = $form->get('myField');

// Do some changes to the field object...

// overwrite the "old" field object
$form->set('myField', $field);

// render the modified form...

@kongondo

Also thanks to you. Searched about wireArrays during my post and so posted after you *g*

No you don't have to set it, just modify the field object and done, it's an instance and not a copy.

Just as a hint. When doing all this form manipulation, just keep in mind that fields could be nested in case of fieldsets containing fields. There's also $form->get("fieldset_details")->children() etc... But you could also get a flat presentation of the inputfields with $inputfieldsArray = $form->getAll(); though not positive it's useful in your case.

Update2

Instead of replace (seems not work with forms) it could be done with two steps...

$form->insertBefore($myField, $form->get('myFormField'));
$form->remove($form->get('myFormField'));

That should work fine.

  • Like 3
Link to comment
Share on other sites

Just as a hint. When doing all this form manipulation, just keep in mind that fields could be nested in case of fieldsets containing fields. There's also $form->get("fieldset_details")->children() etc... But you could also get a flat presentation of the inputfields with $inputfieldsArray = $form->getAll(); though not positive it's useful in your case.

Ok, thanks. At the moment I work with simple forms, but handle nested fields, repeater fields or multi language fields would be nice...

I try to get the submit field "name" attr like this

$btn = $form->find('type=submit');
$btn->name;
// $btn->get('name');
// $btn->attr('name');
// ...

How should I get the submit button name (attr)? Need it to get the input post value to check without hardcode it...

Workaround is to save it during generate the submit button, but I think it should be "readable" from the form object...?

Link to comment
Share on other sites

Found a solution... Maybe there is a better one, but it works...

$form->find("type=submit")->get("type=submit")->name;

Tried also

// not working
$form->get("type=submit")->name;
$form->find("type=submit")->name;

And with a single find I have to use a loop to get it...

$match = $form->find("type=submit");

        foreach ($match as $button) {
            echo $button->name;
        }
Link to comment
Share on other sites

The get() in InputfieldWrapper is assuming to get a field by name and is not using a selector like a find.

/**
* By default, calls to get() are finding a child Inputfield based on the name attribute
*
*/
public function get($key) {
    if($inputfield = $this->getChildByName($key)) return $inputfield;
    if($this->fuel($key)) return $this->fuel($key);
    if($key == 'children') return $this->children;
    if(($value = parent::get($key)) !== null) return $value;
    return null;
}

You could also do 

$form->find("type=submit")->first->name;
  • Like 2
Link to comment
Share on other sites

$form->insertBefore($myField, $form->get('myFormField');

That should work fine.

Tested it without success...

Recoverable Fatal Error: Argument 2 passed to InputfieldWrapper::insertAfter() must be an instance of Inputfield, null given, called in /volume1/web/pwdev/site/modules/FormHelper/FormHelper/FormHelper.module on line 98 and defined (line 201 of /volume1/web/pwdev/wire/core/InputfieldWrapper.php) 

Get field from form isn't a object instance of Inputfield...

Works if I use a field object.

So that not work:

$this->form->insertAfter($this->form->get('title'), $this->form->get('headline'));

Could form field object be converted to an Inputfield object?

Link to comment
Share on other sites

I'm not sure I can follow you. *confused*

I think it's a matter of terms. To be more correct in PW termns there's Fieldtype and Inputfield. Fieldtype is more like the model while the Inputfield is the interface to the user, meaning resposible for rendering the value and inputs of a Fieldtype. Forms are build out of Inputfields. Now a "field" (if using the more general naming) added to a form (InputfieldWrapper) always has to be of type "Inputfield" .

The error you got: You try to add a NULL to the form as the second argument! Now looks like your form get() call doesn't return a Inputfield but NULL so it's not found maybe. But you can easily test that.

But you might know all this already.

Mh, ok. 

Both (input)fields works fine inside the form...

This one was generated from a page.

$fields = $myPage->getInputfields();

foreach ($fields as $field) {
    $this->form->add($field);
}

I'll try it with other form sources... 

I'm not sure I understand, What "both"?

InputfieldFrom (InputfieldWrapper) only allows Inputfields to be added, and not Fields (Fields as you get per a call like $template->fields. If you try to add those you get an error. 

  • Like 1
Link to comment
Share on other sites

Both fields I tried to use are shown correct in the form ;)

So that code should work.

$form->insertAfter($field, $posRef);

...

...Works fine so it must be something you're overlooking. 

:-X

Found and fixed two bugs in my code. Because of the special behavior most tests ok, but sometimes... 

Thank you very much! To know the error isn't that piece of code helped me much. 

Link to comment
Share on other sites

  • 5 months later...

I've a small problem with insertBefore. Somehow it's not working, while I can't see what could be wrong. I'm hooking the FormBuilder Interface and "form_emailForm" is correctly changed to 50% width. If I plainly add the additional field I see it below the whole interface, but if I use insertBefore it's not even to be found in the markup. Also $form->get("fieldsetEmail") does return null, even though this is the parent InputfieldWrapper of form_emailFrom. PW Version is the 2.5.20

	public function addEmailField($event) {
		$form = $event->return;

		$field = $form->get('form_emailFrom');
		$field->columnWidth = 50;

		$additionalField = $this->modules->get("InputfieldEmail");
		$additionalField->columnWidth = 50;
		$additionalField->attr('id+name', 'form_defaultEmailFrom'); 
		$additionalField->attr('value', $form->defaultEmailTo ? $form->defaultEmailTo : ''); 
		$additionalField->label = $text;
		$additionalField->description = $text2; 

		$form->insertBefore($additionalField, $field);
	}
  • Like 1
Link to comment
Share on other sites

Seems like it's not insertBefore per se. I could get the fieldset by using numeral keys on all the children and insertBefore() on the fieldset does work as expected.

var_dump($form->children[1]->children[3]->id); // "fieldsetEmail"
var_dump($form->get('fieldsetEmail')); // null

There's just something with getting the fieldset that just does not work.

  • Like 1
Link to comment
Share on other sites

Another form same problem. This time it's a FormBuilder generated form. I use this in a module to generate a frontend form entry list / single view. FormBuilder itself does use the same syntax for generating it's own entry view, so FormBuilder is broken, too.

$form = $this->forms->get($name);

foreach($form->entries()->get($entryID) as $key => $value) {
  $field = $form->get($key); // returns null for every nested field
}
Link to comment
Share on other sites

This works fine for me.

$form = $modules->InputfieldForm;
$form->action = "./";
$form->method = "post";

$fs = $modules->InputfieldFieldset;
$fs->attr("id+name", "myfieldset");
$fs->label = "My Fieldset";

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

$field = $modules->InputfieldText;
$field->attr("name","firstname");
$field->label = "Firstname";

$fs->add($field);
$form->add($fs);

// insert later
$lastname = $modules->InputfieldText;
$lastname->attr("name","lastname");
$lastname->label = "Lastname";

$fieldset = $form->get("myfieldset");
$firstnamefield = $fieldset->get("firstname");
$fieldset->insertBefore($lastname, $firstnamefield);

$content .= $form->render();
  • Like 1
Link to comment
Share on other sites

Do I really have to ->get() all fieldsets down to where my field is? What boggles me is this:

// $form = edit form of ProcessFormBuilder

$field = $form->get('form_emailFrom'); // returns the correct select field

// try to get the fieldset containing $field
$fieldset1 = $form->get('fieldsetEmail'); // returns null
$fieldset2 = $form->children[1]->children[3]; // returns the fieldset with the id 'fieldsetEmail'

$fieldset1->insertBefore($field, $someotherfield); // this works
$form->insertBefore($field, $someotherfield); // this does not work

I don't see why the first line would work, while getting the fieldset via it's id returns null, even though the fieldset is indeed in the form.

Maybe you can try it with exactly the code I had: https://github.com/LostKobrakai/FormBuilderEmailExtentions/blob/master/FormBuilderEmailExtentions.module#L116

Link to comment
Share on other sites

I don't see through your code and don't understand the why and what and how the form is built.

Does your fieldset have a "name" attribute? It needs one, as the InputfieldWrapper::get() search for "name" key....


Just to mention you can also use find() to search by id:

$fieldset = $form->find("id=myfieldset2")->first();

here the same with nested fieldsets, still works fine:

$form = $modules->InputfieldForm;
$form->action = "./";
$form->method = "post";

$fs = $modules->InputfieldFieldset;
$fs->attr("id+name", "myfieldset");
$fs->label = "My Fieldset";

$fs2 = $modules->InputfieldFieldset;
$fs2->attr("id+name", "myfieldset2");
$fs2->label = "My Fieldset2";

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

$field = $modules->InputfieldText;
$field->attr("name","firstname");
$field->label = "Firstname";

$fs2->add($field);
$fs->add($fs2);
$form->add($fs);

$lastname = $modules->InputfieldText;
$lastname->attr("name","lastname");
$lastname->label = "Lastname";

$fieldset = $form->get("myfieldset2");
$firstnamefield = $fieldset->get("firstname");
$fieldset->insertBefore($lastname, $firstnamefield);

$content .= $form->render();

$fieldset1->insertBefore($field, $someotherfield); // this works
$form->insertBefore($field, $someotherfield); // this does not work

First works cause it's correct, second isn't. You field $someotherfield isn't child of InputfieldWrapper $form. But it is a child of InputfieldWrapper $fieldset1.

  • Like 1
Link to comment
Share on other sites

One more you can also get a field and get its parent InputfieldWrapper:

$lastname = $modules->InputfieldText;
$lastname->attr("name","lastname");
$lastname->label = "Lastname";

$firstnamefield = $form->get("firstname"); 
$fieldset = $firstnamefield->parent;
$fieldset->insertAfter($lastname, $firstnamefield);
  • Like 2
Link to comment
Share on other sites

I see now, why it does not work. With all those attr("id+name", …) I didn't had this on the radar. ProcessFormBuilder does only set a id for it's fieldsets, but not a name, which is really great if one wants to get() those fieldsets.

Edit: thanks for that tip with the parent. This way I don't need that find().

Link to comment
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
 Share

  • Recently Browsing   0 members

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