pwFoo
Members-
Posts
708 -
Joined
-
Last visited
Everything posted by pwFoo
-
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
-
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'));
-
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*
-
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?
-
Form processing on front-end, dynamic forms and creating page
pwFoo replied to Vineet Sawant's topic in Getting Started
It isn't tested with multi language fields or something like repeater fields at the moment. You can generate a form based on saved pages and get a prefilled form as default. Create a form from template fields works with a "fake page" (created but not saved page object), but so you can't use a template with image / file fields that way. You'll get an error message. Maybe it works if the fake page gets saved before the form is generated. I'll see during page add funtion of planned frontend content manager (instead of use a template based form the module create and save the needed page before generate the form via FormHelper. For use with me UserLogin module the third way was added. The login form is defined as data array. Should be the same problem with image / file fields, but haven't tested it... I puplished the module code at the last topic post, but not released a module as yet... Module will be released after code cleanup, but it isn't tested enough to be stable! -
Form processing on front-end, dynamic forms and creating page
pwFoo replied to Vineet Sawant's topic in Getting Started
I write a module FormHelper to create Frontend forms Form page, template vor array oft field data. https://processwire.com/talk/topic/7508-template2form-module-helper/ Next module will be a frontend content manager (edit and create pages based on FormHelper module). -
Nice. Also think about to build a pw solution.
-
Yes, PW is great to learn PHP, module development, hooks...
-
I created a simple login / logout module UserLogin based on my new FormHelper... <?php class UserLogin extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array */ public static function getModuleInfo() { return array( 'title' => 'UserLogin', 'summary' => 'Login and logout frontend users', 'version' => '001', 'requires' => array('FormHelper'), ); } private $formSubmit = array('attr' => array('value' => 'Login')); private $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), 'attr' => array('id+name' => 'password', 'type' => 'password'), ), ); public function login($redirect = null) { $fh = $this->modules->get('FormHelper'); $fh->createForm(array('formFields' => $this->formFields, 'formSubmit' => $this->formSubmit)); $process = $fh->formProcess(); if ($process) { // form ok, sanitizing and execute login process... $user = $this->sanitizer->name($process->get('username')->value); $pass = $process->get('password')->value; // Try to login and redirect after user sucessfully logged in... $login = $this->processLogin($user, $pass, $redirect); // Not rediected after tried login...? Set login error message! $error = "<p style='color:red;'>{$login}</p>"; // should be added to form as InputfieldMarkup return $error . $fh->render(); } // Show login form return $fh->render(); } public function logout($redirect = null) { $this->processLogout($redirect); } protected function ___processLogin($user, $pass, $redirect) { try { $login = $this->session->login($user, $pass); if($login && $login->id) { $this->session->redirect($redirect, false); // redirect - process stops here!!! } else { return "Login failed"; } } catch(Exception $e) { return $e->getMessage(); } } protected function ___processLogout($redirect) { $this->session->logout(); $this->session->redirect($redirect, false); } } Example usage (template code for /user page, URL segments activated)... <?php $fu = $modules->get('UserLogin'); if ($user->isGuest()) { $output = $fu->login("{$config->urls->root}/user"); } elseif ($input->urlSegment1 === 'logout') { $fu->logout("{$config->urls->root}/user"); } else { $output = "Username: {$user->name}<br /><a href='{$config->urls->root}/user/logout'>Logout</a><br />"; } echo '<html><head>'; // 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 $output; echo '</body></html>'; Extensions and improvements planned...
-
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>'; } }
-
Still as php array https://processwire.com/talk/topic/7508-template2form-module-helper/?p=73222
-
After some more ideas and a rewrite again... Should be renamed to FormHelper. Module can create forms by 1) page object 2) 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...
-
The problem ist to find a "simple" data structur as configuration to my form helper. But also should be parsed without much overhead...
-
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...
-
I have build an module with frontend form, but will rewrite it (again) to make it more flexible... https://processwire.com/talk/topic/7508-template2form-module-helper/ But at the source code you should see how it works (inside the module). You also need to build a form! @Martijn Geerts Thank's, was just quick search the forum and paste there
-
You have to load the ckeditor before you output scripts and styles Load the module adds the css and js to $config->scripts and $config->styles. foreach($config->scripts->unique() as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; foreach($config->styles->unique() as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />";
-
After some testing that worked for me // needed by ckeditor! $modules->get('JqueryCore'); // load ckeditor $modules->get('InputfieldCKEditor'); // here you have to build a form with InputfieldForm module and form fields! // Examples: You need js config in the html head section before module styles and scripts! // ckeditor needs some js config BEFORE you load the module styles and scripts <script type="text/javascript"> <?php $jsConfig = $config->js(); $jsConfig['debug'] = $config->debug; $jsConfig['urls'] = array( 'root' => $config->urls->root, 'admin' => $config->urls->admin, 'modules' => $config->urls->modules, 'core' => $config->urls->core, 'files' => $config->urls->files, 'templates' => $config->urls->templates, 'adminTemplates' => $config->urls->adminTemplates, ); ?> var config = <?php echo json_encode($jsConfig); ?>; </script> After that, you can output the modules styles and scripts foreach($config->scripts->unique() as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; foreach($config->styles->unique() as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />";
-
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...?
-
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?
-
Updated code and example usage... Feedback and suggestions would be great
-
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?
-
same works with Profile after login echo $modules->get('ProcessProfile')->execute(); Have to test and think about ProcessProfile vs. user page as profile... But maybe ProcessProfile is a alternative to custom user prolfile pages.
-
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.
-
@Kixe Yes, $session->login and a little bit sanitizing values Works fine, but changed it for testing to use ProcessLogin instead, but login failed without error message. So my custom function is more flexible for my use case (works fine, simple to hook in and know the code *g*)
-
Custom login can be realized with few lines of code... also works fine with inline error messages. ProcessLogin doesn't show inline errors. How can this behaviour changed via form API?