pwFoo Posted September 7, 2014 Share Posted September 7, 2014 Hi, during work on some own modules (frontend content manager, frontend users) I noticed my need of a helper module. Template2Form (working title) is a module to build a form based on fields get from a page object or a template file (tmp fake page object). During build process each field could be hooked in to modify it. Also it's possible to modifiy form, submit button and form fields via function params. It's my first (basic / dev state) module I post here... If it will be useable I have to clean up and comment the code well... template2form class <?php /** * Processwire 'template2form' module * * template2form - generate form from page / template fields * * @author pwFoo * @since 2014-07-18 * * ProcessWire 2.x * Copyright (C) 2011 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://www.processwire.com * http://www.ryancramer.com */ class Template2Form extends WireData implements Module { /** * @var object $form generated form object */ public $form; /** * @var array $option multidimensional array with options */ private $option; /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * @return array */ public static function getModuleInfo() { return array( 'title' => 'Template2Form', 'summary' => 'Generate form from template fields', 'version' => '0.0.1', ); } /** * Default module and form options * @var array $defaultOptions static mutlidimensional array with default options */ public static $defaultOptions = array( 'page' => null, 'template' => null, 'prefillFormFields' => null, 'jquery' => null, 'form' => array('method' => 'post', 'action' => '', 'id' => 'login', 'name' => 'login'), 'formSubmit' => array('id' => 'submit', 'name' => 'submit', 'value' => 'Submit'), 'formFields' => null, ); public function init() { $this->addHookAfter('Template2Form::buildField', $this, 'hookingFormField', array('priority'=>20)); } /** * Set / merge module and form options * @param array $options Array with given options * @return null */ private function setOptions (array $options = null) { if($options != null && is_array($options)) { $this->option = array_replace_recursive(self::$defaultOptions, $options); // Use template instead of page if given if ($this->option['template] !== null) { $this->option['page'] = $this->fakePage($this->option['template']); } // No template or page? Use current page... elseif ($this->option['template'] === null) { $this->option['page'] = $this->page; } if ($this->option['jquery']) { $this->modules->get('JqueryCore'); } } else { $this->option = self::$defaultOptions; } } /** * Generate the form object * @param array $options Set of optional and needed settings * @return object Generated form */ public function getForm (array $options = null) { $this->setOptions($options); $this->form = $this->buildForm (); return $this->form; } /** * Generate the form object from given fields * @return object Generated form */ private function buildForm () { $form = $this->modules->get('InputfieldForm'); $form = $this->setFormAttr($form); // Get fields to build the form $fields = $this->templates->get($this->option['page']->template)->fields; foreach ($fields as $field) { $f = $this->buildField ($field); // Get Inputfield object if ($f !== NULL) $form->append($f); // Remove NULLed fields from from... } $form->append($this->addSubmitButton()); return $form; } /** * Set form attributes and return the object * @param object $form * @return object Form with added attributes */ protected function ___setFormAttr($form) { $form->id = $this->option['form']['id']; $form->name = $this->option['form']['name']; $form->action = $this->option['form']['action']; $form->method = $this->option['form']['method']; return $form; } /** * Generate Inputfield object from given field object * @param object $field Page field object * @return object */ protected function ___buildField ($field) { return $field->getInputfield($this->option['page']); } /** * Modify the current field object by hook in after buildField function * @param object $event */ protected function ___hookingFormField ($event) { $field = $event->return; $hook = $this->option['formFields'][$field->name]; // Remove selected field... if ($hook['remove'] == true) { $event->return = NULL; } // prefill form fields from page value... elseif ($this->option['prefillFormFields'] && $event->page->get($field->name)) { $hook['set']['value'] = $event->page->get($field->name); } if (!isset($hook)) return; // nothing to do with this field... // Set form field values... elseif (is_array($hook['set'])) { foreach ($hook['set'] as $key => $value) { $field->set($key, $value); } $event->return = $field; } } /** * Build the form submit button * @return object form submit Inputfield */ protected function ___addSubmitButton() { $btn = $this->modules->get('InputfieldSubmit'); $btn->attr('id', $this->option['formSubmit']['id']); $btn->attr('name', $this->option['formSubmit']['name']); $btn->attr('value', $this->option['formSubmit']['value']); return $btn; } /** * Rendering the current form * @return string Rendered form as html code */ public function ___formRender() { return $this->form->render(); } /** * Process form data if send * @return object Processed form data */ public function ___formProcess() { $submit = $this->option['formSubmit']['id']; if(!$this->input->post->$submit) return NULL; // form NOT submitted... $processedForm = $this->form->processInput($this->input->post); // form api process form values if(!$this->form->getErrors()) return $processedForm; // form processed: OK else return false; // form send with errors } /** * Make fake page and assign needed template * @param string $tpl Template to assign * @return object Generated fake page to work with */ private function fakePage($tpl) { $fakePage = new Page(); $fakePage->template = $tpl; return $fakePage; } /** * jsConfig settings needed by wysiwyg editor * @return string Basic JavaScript config */ public function ___jsConfig () { $jsConfig = $this->config->js(); $jsConfig['debug'] = $this->config->debug; $jsConfig['urls'] = array( 'root' => $this->config->urls->root, 'admin' => $this->config->urls->admin, 'modules' => $this->config->urls->modules, 'core' => $this->config->urls->core, 'files' => $this->config->urls->files, 'templates' => $this->config->urls->templates, 'adminTemplates' => $this->config->urls->adminTemplates, ); return '<script type="text/javascript">var config = ' . json_encode($jsConfig) . '</script>'; } } Usage examples $t2f = $modules->get('Template2Form'); // Remove field 'headline' and 'body' from form $hookFormFields['headline'] = array('remove' => true); $hookFormFields['body'] = array('remove' => true); // Set / Overwrite field attributes / values like you could do with form api $hookFormFields['title'] = array('set' => array('value' => 'CustomTitle...', 'type' => 'password')); $hookFormFields['summary'] = array('set' => array('value' => 'My overwritten summary...')); // Overwrite submit button attributes (default: id, name, value) $hookFormSubmit = array('value' => 'Speichern'); /* * Build the multidemensional array * page (object) or template (string) -- to build the form from * prefillFormFields -- prefill fields (for example to build a frontend edit page * jquery -- Load JqueryCore module (during getForm() call) * form -- set form attributes / values * formFields -- array to set field values / attributes, take a look at form api examples * formSubmit -- set form submit button attributes / values */ $formOptions = array('page' => $page, 'template' => null, 'prefillFormFields' => true, 'jquery' => true 'formFields' => $hookFormFields, 'formSubmit' => $hookFormSubmit); // Generate the form and set options above $t2f->getForm($formOptions); // process form and return processed form date $process = $t2f->formProcess(); if ($process === NULL) // form not sent elseif ($process === false) // form sent, but with errors elseif ($process == true) // form sent without errors // Render form... $form = $t2f->formRender(); echo '<html><head>'; // jsConfig needed by ckeditor echo $t2f->jsConfig() . "\n"; // outpunt needed scripts for inputfield modules, ... foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; } foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } echo '</head><body>'; echo $form; // output form echo '</body></html>'; 9 Link to comment Share on other sites More sharing options...
pwFoo Posted September 9, 2014 Author Share Posted September 9, 2014 Changed some little things (array_merge changed to array_replace_recursive because of sub arrays at options). Seems to work now how expected. Because nobody other than me needs such a module I won't release it as a module and simply test and use it inside my application. Link to comment Share on other sites More sharing options...
SiNNuT Posted September 9, 2014 Share Posted September 9, 2014 Changed some little things (array_merge changed to array_replace_recursive because of sub arrays at options). Seems to work now how expected. Because nobody other than me needs such a module I won't release it as a module and simply test and use it inside my application. Don't be discouraged by the absence of replies within the first couple of days. It sounds interesting and like something that could be useful to others as well, so keep at it. 2 Link to comment Share on other sites More sharing options...
pwFoo Posted September 10, 2014 Author Share Posted September 10, 2014 Ok, helper module is used by my own frontend user module (at the moment a simple login, register, logout module) which is extendable (email activiation, backend plugins,...) and it seems to work fine. But before I can release it as a public module I have to do some more clean up and comments on the code... Also feedback is appreciated because it's my first module. naming convention? what could/ should be improved or simplyfied? Link to comment Share on other sites More sharing options...
pwFoo Posted September 11, 2014 Author Share Posted September 11, 2014 Updated code and example usage... Feedback and suggestions would be great 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 11, 2014 Author Share Posted September 11, 2014 Modules based on template2form module FrontendUsers (basically done - rewrite, optimize and add optional features)login, logout, register frontend users, backend plugins to implement for example ldap auth (login, register form added as templates to work with template2form module) FrontendContentManager (edit function works as proof of concept, but have to be improved and tested with repeater fields and language support...)edit and create content as frontend user FrontendProfile (planned)user pages / profiles, owner editable, extendable Template2Form... shouldn't it be renamed...?! Somewhere I read an recommendation about module names. Because of form building it could be start with "Form..."? Any idea? 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 12, 2014 Author Share Posted September 12, 2014 Thinking about how to build my login and register form during module rewrite... Build a register form based on a PW template (simply add fields to template to expand the register form generated by template2form module...) could be nice, but what's with a simple login form? Login form via template2form needs a template "form_login" with the fields "username" and "password". Should such a form better build via form api at source code? Is a template file with to fields to much overhead or see you any advantage to do it that way? But with the module the form process is simplyfied (needed code is implemented). template2form is primary build as a universal module / helper to generate a page frontend edit form. Could be also used for login and register forms, but should I do...? Link to comment Share on other sites More sharing options...
pwFoo Posted September 13, 2014 Author Share Posted September 13, 2014 After some more ideas and a rewrite again...Should be renamed to FormHelper. Module can create forms by 1) page object2) template (fields)3) array of field data (new) It's possible to skipFields (array of field names), clearFormValues (field values removed), changeable form and submit button values, take care of jsConfig and also JqueryCore module load.So ckeditor works out of the box (if output order is correct at template...) Example how to build a login form with username and password fields... $fh = $modules->get('FormHelper'); // Create a username form field -- fieldVars 'name' is required to build $field->name $fieldVars = array('name' => 'username', 'label' => 'Username', 'required' => true); $fieldAttr = array('id+name' => 'username'); $field = array('module' => 'InputfieldText', 'vars' => $fieldVars, 'attr' => $fieldAttr); $formFields[] = $field; // Second form field... password $fieldVars = array('name' => 'password', 'label' => 'Password', 'required' => true); $fieldAttr = array('id+name' => 'password', 'type' => 'password'); $field = array('module' => 'InputfieldText', 'vars' => $fieldVars, 'attr' => $fieldAttr); $formFields[] = $field; // Change submit button value from "Submit" to "Login" $formSubmit = array('attr' => array('value' => 'Login')); // Generate the form $fh->createForm(array('formSubmit' => $formSubmit, 'formFields' => $formFields)); // process form $process = $fh->formProcess(); // check result of form process if ($process === NULL) // not send elseif ($process == true) // send, without errors elseif ($process === false) // send, but with errors $form = $fh->render(); // returns rendered form echo '<html><head>'; // jsConfig needed by wysiwyg editors echo $fh->jsConfig() . "\n"; // outpunt needed scripts for inputfield modules, ... foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; } foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } echo '</head><body>'; echo $form; echo '</body></html>'; Generate form of current page (with ckeditor loaded for body field... jquery is needed) $fh->createForm(array('jquery' => true)); Generate form from given page object $fh->createForm(array('page' => $pages->get('/'))); // or without prefilled form field values $fh->createForm(array('page' => $pages->get('/'), 'clearFormValues' => true)); And form based on template fields $fh->createForm(array('template' => 'sitemap')); Known bug with form generated based on a template instead an existing page! You get an error if a form should be generated from a template with fiel fields (like images)! Because of a fakePage object You'll get this error message. Error: Exception: New page '/pwdev//' must be saved before files can be accessed from it (in /volume1/web/pwdev/wire/core/PagefilesManager.php line 240) #0 /volume1/web/pwdev/wire/core/PagefilesManager.php(211): PagefilesManager->path() #1 /volume1/web/pwdev/wire/core/PagefilesManager.php(67): PagefilesManager->createPath() #2 /volume1/web/pwdev/wire/core/PagefilesManager.php(55): PagefilesManager->init(Object(Page)) #3 /volume1/web/pwdev/wire/core/Page.php(1625): PagefilesManager->__construct(Object(Page)) #4 /volume1/web/pwdev/wire/core/Pagefiles.php(74): Page->filesManager() #5 /volume1/web/pwdev/wire/core/Pagefiles.php(58): Pagefiles->setPage(Object(Page)) #6 /volume1/web/pwdev/wire/modules/Fieldtype/FieldtypeImage.module(33): Pagefiles->__construct(Object(Page)) #7 /volume1/web/pwdev/wire/core/Fieldtype.php(374): FieldtypeImage->getBlankValue(Object(Page), Object(Field)) #8 /volume1/web/pwdev/wire/core/Page.php(760): Fieldtype->getDefaultValue(Object(Page), Object(Field)) #9 /volume1/web/pwdev/wire/core/Page.p To create new pages with FormHelper your module have to create the page first.Maybe there is a solution... but I don't know at the moment.Also it's not a problem for my needs. Editing pages works fine and if a module try to create a new page it simply should saved via api before FormHelper build the form... 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 14, 2014 Author Share Posted September 14, 2014 The latest (and first build *g*) of FormHelper module. (Untested with repeater fields or multi language pages) <?php /** * Processwire 'FormHelper' module * * Generate forms from pages, templates or input data * * @author pwFoo * @since 2014-09-13 * * ProcessWire 2.x * Copyright (C) 2011 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://www.processwire.com * http://www.ryancramer.com */ class FormHelper extends WireData implements Module { protected $form; protected $field; protected $submitBtn; protected $option; /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * @return array */ public static function getModuleInfo() { return array( 'title' => 'FormHelper', 'summary' => 'Generate and process forms from page / template fields or given field parameters', 'version' => '0.0.1', ); } /** * Default module and form options * @var array $defaultOptions static mutlidimensional array with default options */ private static $defaultOptions = array( // Use page, template or given formFields array data 'page' => null, 'template' => null, 'formFields' => null, // form, fields and submit button basics 'form' => array( 'module' => 'InputfieldForm', 'vars' => array('method' => 'post', 'action' => ''), 'attr' => array('id+name' => 'formhelper'), ), 'formSubmit' => array( 'module' => 'InputfieldSubmit', 'attr' => array ('id' => 'submit', 'name' => 'submit', 'value' => 'Submit'), ), 'formFields' => null, // module options 'clearFormValues' => null, 'jquery' => null, ); /** * Set / merge module and form options * @param array $options Array with given options * @return null */ private function setupOptions (array $options = null) { if($options != null && is_array($options)) { $this->option = array_replace_recursive(self::$defaultOptions, $options); } else { $this->option = self::$defaultOptions; } // Use template instead of page if given if ($this->option['template'] !== null) { $this->option['page'] = $this->fakePage($this->option['template']); } // No template or page set? Also no formFields defined? Use current page... elseif ($this->option['page'] === null && $this->option['formFields'] === null) { $this->option['page'] = $this->page; } // jQuery module should be loaded early because it's needed by for example ckeditor if ($this->option['jquery']) { $this->modules->get('JqueryCore'); } } /** * Generate the form object from given fields * @return object Generated form */ public function ___createForm (array $options = null) { $this->setupOptions($options); // set options // create form field / wrapper $this->form = $this->setObj($this->option['form']); // Get inputfields from page object or given template if ($this->option['page'] || $this->option['template']) { $inputfields = $this->getFormInputfields(); } // ... or a user given form data structure elseif ($this->option['formFields'] !== null && is_array($this->option['formFields'])) { $inputfields = $this->createFormFields(); } // add fields to form... foreach($inputfields as $inputfield) { if ($field = $this->prepareField($inputfield)) { $this->form->add($field); $this->field[$field->attr('name')] = $field; } } // add submit button $this->submitBtn = $this->setObj($this->option['formSubmit']); $this->form->add($this->submitBtn); return $this->form; } /** * */ protected function ___prepareField($field) { if(in_array($field->name, $this->option['skipFields'])) return null; // remove field if ($this->option['clearFormValues']) $field->value = null; // set value to empty return $field; } /** * Generate inputfields from given page object fields * @return object Generated field */ protected function getFormInputfields () { if (!$this->option['page']) { $this->option['page'] = $this->fakePage($this->option['template']); } return $this->option['page']->getInputfields(); } /** * Generate form fields based on given data array * @return object Generated field */ protected function createFormFields() { foreach ($this->option['formFields'] as $formField) { $field = $this->setObj($formField); $inputfields[$field->name] = $field; } return $inputfields; } /** * Rendering the current form * @return string Rendered form as html code */ public function ___render() { return $this->form->render(); } /** * Process form data if send * @return object Processed form data */ public function ___formProcess() { $submit = $this->submitBtn->get('name'); if(!$this->input->post->$submit) return NULL; // form NOT submitted... $processedForm = $this->form->processInput($this->input->post); // form api process form values if(!$this->form->getErrors()) return $processedForm; // form processed: OK else return false; // form send with errors } /** * Generate a field / form object * @param array $arr Needed values to create the object * @return object Generated field object */ private function setObj($arr) { $obj = $this->modules->get($arr['module']); $this->setObjVars($obj, $arr['vars']); $this->setObjVars($obj, $arr['attr']); return $obj; } /** * Set field object variables * @param object $obj field object by reference * @param array $arr field variable values */ private function setObjVars(&$obj, $arr) { foreach ($arr as $key => $value) { $obj->set($key, $value); } } /** * Set field object attribues * @param object $obj field object by reference * @param array $arr field attribute values */ private function setObjAttr(&$obj, $arr) { foreach ($arr['attr'] as $key => $value) { $obj->attr($key, $value); } } /** * Make fake page and assign needed template * @param string $tpl Template to assign * @return object Generated fake page to work with */ private function fakePage($tpl) { $fakePage = new Page(); $fakePage->template = $tpl; return $fakePage; } /** * jsConfig settings needed by wysiwyg editor * @return string Basic JavaScript config */ public function ___jsConfig () { $jsConfig = $this->config->js(); $jsConfig['debug'] = $this->config->debug; $jsConfig['urls'] = array( 'root' => $this->config->urls->root, 'admin' => $this->config->urls->admin, 'modules' => $this->config->urls->modules, 'core' => $this->config->urls->core, 'files' => $this->config->urls->files, 'templates' => $this->config->urls->templates, 'adminTemplates' => $this->config->urls->adminTemplates, ); return '<script type="text/javascript">var config = ' . json_encode($jsConfig) . '</script>'; } } Link to comment Share on other sites More sharing options...
fmgujju Posted September 23, 2014 Share Posted September 23, 2014 Where can I download your module? I don't see any GitHub or any other link. I believe I need to copy the above code and create a module in PW. I would like to test your module. Thanks! Link to comment Share on other sites More sharing options...
pwFoo Posted September 23, 2014 Author Share Posted September 23, 2014 Hello fmgujju, after diving deeper into form api I rewrite the module code again. I try to get it more flexible and easier / much shorter... Minor options / parameter changes Feature to merge (maybe also replace and insert at position...) page / template fields with additional values / overwrite from array data get the form object and do whatever you want via form api (before render the form) At the moment you can copy the module code above to do some tests...https://processwire.com/talk/topic/7508-template2form-module-helper/?p=73255 Maybe I can update the module code or maybe build a release until the end of the week... Link to comment Share on other sites More sharing options...
pwFoo Posted September 23, 2014 Author Share Posted September 23, 2014 Here an updated / reworked module version... <?php /** * Processwire 'FormHelper' module * * Generate forms from pages, templates or input data * * @author pwFoo * @since 2014-09-13 * * ProcessWire 2.x * Copyright (C) 2011 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://www.processwire.com * http://www.ryancramer.com */ class FormHelper extends WireData implements Module { protected $form; protected $submitBtn; protected $cfg = array( 'page' => null, 'template' => null, 'clearFormValues' => null, 'jquery' => null, 'jsconfig' => null, // form default settings 'form' => array( 'module' => 'InputfieldForm', 'vars' => array('method' => 'post', 'action' => ''), 'attr' => array('id+name' => 'formhelper'), ), 'submit' => array( 'module' => 'InputfieldSubmit', 'attr' => array ('id' => 'submit', 'name' => 'submit', 'value' => 'Submit'), ), 'fields' => null, /* * 'fields' => array( * 'username' => array( * 'module' => 'InputfieldText', * 'position' => 'insertBefore:password', // "insert method" [":" "reference field"] * 'vars' => array('name' => 'username', 'label' => 'Username', 'required' => true), // var "name" required! * 'attr' => array('id+name' => 'username'), * ), * ), */ ); /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * @return array */ public static function getModuleInfo() { return array( 'title' => 'FormHelper', 'summary' => 'Generate and process forms from page / template fields or given field parameters', 'version' => '0.0.2', ); } protected function setCfg ($arr, $reset = null) { if ($reset === null) { $this->cfg = array_replace_recursive($this->cfg, $arr); } else { $this->cfg = $arr; } } /** * Generate the form object from given fields * @return object Generated form */ public function ___createForm (array $cfg = null, $reset = null) { // merge or overwrite default config if ($cfg !== null) $this->setCfg($cfg, $reset); // create form field / wrapper $this->form = $this->setObj($this->cfg['form']); // Get inputfields from page object or given template if ($this->cfg['page'] || $this->cfg['template']) $this->getFormInputfields(); // create or merge form with given field data array if ($this->cfg['fields'] !== null && is_array($this->cfg['fields'])) $this->createFormFields(); // add submit button $this->submitBtn = $this->setObj($this->cfg['submit']); $this->form->add($this->submitBtn); return $this->form; } /** * ToDo: implement method / field positioning ? */ public function formField ($field, $method = 'add', $posRefField = null) { $field = $this->prepareField($field); $this->form->$method($field); } /** * */ protected function ___prepareField($field) { if(in_array($field->name, $this->cfg['skipFields'])) return null; // remove field if ($this->cfg['clearFormValues']) $field->value = null; // set value to empty return $field; } /** * Generate inputfields from given page object fields * @return object Generated field */ protected function getFormInputfields () { if ($this->cfg['template'] && !$this->cfg['page']) { $this->cfg['page'] = $this->fakePage($this->cfg['template']); } foreach ($this->cfg['page']->getInputfields() as $field) { $this->formField($field); } } /** * Generate form fields based on given data array * @return object Generated field */ protected function createFormFields() { foreach ($this->cfg['fields'] as $formField) { // Update form field if exists if ($exists = $this->form->get($formField['vars']['name'])) { $this->setObjValues($exists, $formField); } // Doesn't exist? Create and add it to form... else { $field = $this->setObj($formField); $this->formField($field); } } } /** * Rendering the current form * @return string Rendered form as html code */ public function ___render() { return $this->form->render(); } /** * Process form data if send * @return object Processed form data */ public function ___formProcess() { $submit = $this->submitBtn->get('name'); if(!$this->input->post->$submit) return NULL; // form NOT submitted... $processedForm = $this->form->processInput($this->input->post); // form api process form values if(!$this->form->getErrors()) return $processedForm; // form processed: OK else return false; // form send with errors } /** * Generate a field / form object * @param array $arr Needed values to create the object * @return object Generated field object */ private function setObj($arr) { $obj = $this->modules->get($arr['module']); $this->setObjValues($obj, $arr); return $obj; } /** * Update form / field variables and values * @param object $obj field object by reference * @param array $arr field variables/ properties and attributes */ private function setObjValues(&$obj, $arr) { if (is_array($arr['vars'])) { foreach ($arr['vars'] as $key => $value) { $obj->set($key, $value); } } elseif (is_array($arr['attr'])) { foreach ($arr['attr'] as $key => $value) { $obj->set($key, $value); } } } /** * Make fake page and assign needed template * @param string $tpl Template to assign * @return object Generated fake page to work with */ private function fakePage($tpl) { $fakePage = new Page(); $fakePage->template = $tpl; return $fakePage; } /** * jsConfig settings needed by wysiwyg editor * @return string Basic JavaScript config */ public function ___jsConfig () { $jsConfig = $this->config->js(); $jsConfig['debug'] = $this->config->debug; $jsConfig['urls'] = array( 'root' => $this->config->urls->root, 'admin' => $this->config->urls->admin, 'modules' => $this->config->urls->modules, 'core' => $this->config->urls->core, 'files' => $this->config->urls->files, 'templates' => $this->config->urls->templates, 'adminTemplates' => $this->config->urls->adminTemplates, ); return '<script type="text/javascript">var config = ' . json_encode($jsConfig) . '</script>'; } } Some features (jquery, jsconfig, ...) missing, but it works with a simple page / template... My testing template code (also with form field overwrite (for example field username). <?php $fh = $modules->get('FormHelper'); $formFields['username'] = array( 'module' => 'InputfieldText', 'vars' => array('name' => 'username', 'label' => 'Username123', 'required' => true), 'attr' => array('id+name' => 'username'), ); $fh->createForm(array('template' => 'register', 'fields' => $formFields)); // process form $process = $fh->formProcess(); if ($process === NULL) { echo "Nicht abgeschickt<br /> <br />"; } elseif ($process == true) { echo "Abgeschickt, ohne Fehler<br /> <br />"; } elseif ($process === false) { echo "Abgeschickt, mit Fehlern<br /> <br />"; } $form = $fh->render(); // returns rendered form echo '<html><head>'; // jsConfig needed by wysiwyg editors echo $fh->jsConfig() . "\n"; // outpunt needed scripts for inputfield modules, ... foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; } foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } echo '</head><body>'; echo $form; echo '</body></html>'; Be careful... don't use "$fields" as variable to build the form fields data array. I should change the array key 'fields' again because it lead to use $fields as variable to build the sub array... UPDATE Latest version also fixed a bug during set field properties / attributes... 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 25, 2014 Author Share Posted September 25, 2014 Bitbucket FormHelper Repo is online... dev / unstable !!! https://bitbucket.org/pwFoo/formhelper/src/8ca0b543d87b5534ac476d2e240466a216d34be6/FormHelper/FormHelper.module?at=master Sorry, readme file isn't readable online... It's a simple example usage php file. I paste it here... <?php $fh = $modules->get('FormHelper'); ////////////////////// ////// EXAMPLES ////// // form based on template object $fh->createForm($templates->get('myTemplate')); // form based on page object $fh->createForm($pages->get('myPage')); // form based on a page, but clear field values and remove the fields headline, sidebar $fh->createForm($pages->get('myPage'), array('clearValues' => true, 'skipFields' => array('headline', 'sidebar'))); // Build form from template register and then modifiy username field label... $formFields['username'] = array( 'module' => 'InputfieldText', 'vars' => array('name' => 'username', 'label' => 'Username123', 'required' => true), 'attr' => array('id+name' => 'username'), ); $fh->createForm($templates->get('register'), array('fields' => $formFields)); // Create a login form from array data only and change default "Submit" to "Login" $formSubmit = array('vars' => array('name' => 'submit'), 'attr' => array('value' => 'Login')); $formFields = array( 'username' => array( 'module' => 'InputfieldText', 'vars' => array('name' => 'username', 'label' => 'Username', 'required' => true), 'attr' => array('id+name' => 'username'), ), 'password' => array( 'module' => 'InputfieldText', 'vars' => array('name' => 'password', 'label' => 'Password', 'required' => true, 'type' => 'password'), 'attr' => array('id+name' => 'password', 'type' => 'password'), ), ); $fh->createForm($this->formFields, array('submit' => $this->formSubmit)); ////// EXAMPLES ////// ////////////////////// // process form $process = $fh->formProcess(); if ($process === NULL) { // form not sent } elseif ($process == true) { // form sent, without errors... do something } elseif ($process === false) { // form sent, but with errors! ... } $form = $fh->render(); // returns rendered form echo '<html><head>'; // jsConfig needed by wysiwyg editors echo $fh->jsConfig() . "\n"; // outpunt needed scripts for inputfield modules, ... foreach ($config->scripts as $file) { echo "<script type='text/javascript' src='$file'></script>\n"; } foreach ($config->styles as $file) { echo "<link type='text/css' href='$file' rel='stylesheet' />\n"; } echo '</head><body>'; echo $form; echo '</body></html>'; 1 Link to comment Share on other sites More sharing options...
pwFoo Posted September 26, 2014 Author Share Posted September 26, 2014 The above linked version internal adds all fields (field objects and also field array data) with one function. public function field($field, $method = 'add', $refPosObj = null, $bypass = null) $field: field object OR array of field information to add (inputfield module and field name required) OR update (also field name required) if exists $method: add, insertBefore, remove, ... to build the "$form->$method()" call. $refPosObj: is needed by $method insertAfter or insertBefore. Have to be a field object $bypass: Skip hookable prepare / validate function (used tro handle "skipFields", or "clearValues") before add to form So after create the form it should be possible to modify it with a $fh->field(...) call or directly change the form object $fh->form from outside. This two cases are untested, but forms fine from inside... Link to comment Share on other sites More sharing options...
pwFoo Posted September 26, 2014 Author Share Posted September 26, 2014 And again some changes Some bugs fixed and repo is updated. At the moment I prefer as parameters to build a form parameter 1: fields as objects or array data parameter 2: only module options like "clearValues", "skipFields", ... (but additional field data like change submit button, form attributes or also fields is still possible until now...) Build the form and then modify could be done in two steps. Here an example. $fh->createForm($templates->get('register'), array('clearValues' => false, 'jquery' => false)); $modifyFields['username'] = array( //'module' => 'InputfieldText', 'pos' => array('method' => 'insertAfter', 'refObj' => $fh->form->get('email')), 'vars' => array('name' => 'username', 'label' => 'Username123'), ); $modifyFields['submit'] = array( 'vars' => array('name' => 'submit'), 'attr' => array('value' => 'Login'), ); echo "Before modify: " . $fh->form->get('submit')->value . "<br />"; foreach ($modifyFields as $modifyField) { $fh->field($modifyField); } echo "After modify: " . $fh->form->get('submit')->value . "<br />"; Link to comment Share on other sites More sharing options...
pwFoo Posted October 8, 2014 Author Share Posted October 8, 2014 Released a first dev / unstable module FormHelper for testing... https://processwire.com/talk/topic/7860-module-formhelper/ 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