pwFoo Posted September 22, 2014 Share Posted September 22, 2014 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 More sharing options...
Soma Posted September 22, 2014 Share Posted September 22, 2014 Yah as you speak $form->get('field') or find.. Basically it's a WireArray. Rings a bell? 4 Link to comment Share on other sites More sharing options...
kongondo Posted September 22, 2014 Share Posted September 22, 2014 ....how to manipulate WireArrays http://processwire.com/api/arrays/ 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 22, 2014 Author Share Posted September 22, 2014 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 More sharing options...
pwFoo Posted September 22, 2014 Author Share Posted September 22, 2014 (edited) 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 September 22, 2014 by pwFoo Link to comment Share on other sites More sharing options...
pwFoo Posted September 23, 2014 Author Share Posted September 23, 2014 Last question to that topic... I hope so *g* How to reorder form fields? One solution should be to build a second array in new order and overwrite the original array... But maybe there is a simple build in sort option Link to comment Share on other sites More sharing options...
Soma Posted September 23, 2014 Share Posted September 23, 2014 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. 3 Link to comment Share on other sites More sharing options...
pwFoo Posted September 23, 2014 Author Share Posted September 23, 2014 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 More sharing options...
pwFoo Posted September 25, 2014 Author Share Posted September 25, 2014 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 More sharing options...
Soma Posted September 25, 2014 Share Posted September 25, 2014 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; 2 Link to comment Share on other sites More sharing options...
pwFoo Posted September 25, 2014 Author Share Posted September 25, 2014 @Soma To easy... Works also and looks better. Thanks again! Link to comment Share on other sites More sharing options...
pwFoo Posted September 25, 2014 Author Share Posted September 25, 2014 $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 More sharing options...
Soma Posted September 25, 2014 Share Posted September 25, 2014 In forms it's always inputfields there are no "fields". Works fine so it must be something you're overlooking. Link to comment Share on other sites More sharing options...
pwFoo Posted September 25, 2014 Author Share Posted September 25, 2014 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... Link to comment Share on other sites More sharing options...
Soma Posted September 25, 2014 Share Posted September 25, 2014 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. 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 25, 2014 Author Share Posted September 25, 2014 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. 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 More sharing options...
LostKobrakai Posted February 27, 2015 Share Posted February 27, 2015 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); } 1 Link to comment Share on other sites More sharing options...
renobird Posted February 27, 2015 Share Posted February 27, 2015 I can confirm this on PW 2.5.3 as well. Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 2, 2015 Share Posted March 2, 2015 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. 1 Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 3, 2015 Share Posted March 3, 2015 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 More sharing options...
Soma Posted March 3, 2015 Share Posted March 3, 2015 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(); 1 Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 3, 2015 Share Posted March 3, 2015 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 More sharing options...
Soma Posted March 3, 2015 Share Posted March 3, 2015 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. 1 Link to comment Share on other sites More sharing options...
Soma Posted March 3, 2015 Share Posted March 3, 2015 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); 2 Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 3, 2015 Share Posted March 3, 2015 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now