Jump to content


Photo

Module want: form builder


  • Please log in to reply
74 replies to this topic

#61 diogo

diogo

    Hero Member

  • Moderators
  • 1,982 posts
  • 1061

  • LocationPorto, Portugal

Posted 18 May 2012 - 11:24 AM

I was working over this code from apeisa http://processwire.c...t__20#entry1364 and wanted to share the result with you all.

Basically, this allows you to mirror the admin form from a given page to the frontend.
To give some flexibility, you can fill an array with the fields to exclude —or else, the fields to include— on the output.

EDIT: I forgot to tell... this works well with regular fields (text, textareas, checkboxes, radios, multiple choice, etc), but didn't manage to make it work well with images, for instance.

So, here is the code:
<?php

// Get the page you need to edit
$mypage = $pages->get('/some/page/');

// Populate with the names of the fields you want to exclude OR include (see instructions below)
// Leave empty to output all the fields
$myfields = array('body', 'email');
$form = $modules->get('InputfieldForm');
$fields = $mypage->getInputfields();

// If array is not empty use it to filter the fields
if ($myfields){
	foreach($fields as $f){
		// Output all the fields minus the ones listed in the $myfields array
		// Instead, to output only the fields that are in the array, remove the (!) from the condition
		if (!in_array($f->name, $myfields)){
			$form->append($f);
		}
	}
}

// Else, include all the fields
else {
	$form->append($fields);
}

// Add save button
$field = $this->modules->get('InputfieldSubmit');
$field->attr('id+name', 'submit_save');
$field->attr('value', 'Save');
$field->label = "submit herei";
$form->append($field);

// Process the form
// (code replaced by a new one provided by Ryan)
if($input->post->submit_save) {
	$form->processInput($input->post);
	if(!$form->getErrors()) {
		$mypage->of(false); // turn off output formatting before setting values
		foreach($mypage->fields as $f) {
			$mypage->set($f->name, $form->get($f->name)->value);
		}
	}
}

include("./head.inc");

// Render the form
echo $form->render();

include("./foot.inc");

Edited by diogo, 19 May 2012 - 02:19 PM.


#62 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3107

  • LocationAtlanta, GA

Posted 19 May 2012 - 01:10 PM

Looks good Diogo, thanks for posting. Only thing I wanted to mention is that it may be preferable to get the field value from the Inputfield rather than directly from $input->post. That's because the inputfield may perform some of it's own validation, providing you with a safer value. Though fieldtypes do some validation too, so your method isn't bad either. But getting values from the Inputfields themselves is preferable in many cases. Especially if you wan to display the form again with populated values, like if there's a missing required field or something. So your form processing could look something like this:

if($input->post->submit_save) {
    $form->processInput($input->post); 
    if(!$form->getErrors()) {
        $mypage->of(false); // turn off output formatting before setting values
        foreach($mypage->fields as $f) {
            $mypage->set($f->name, $form->get($f->name)->value); 
        }
    }
}


#63 diogo

diogo

    Hero Member

  • Moderators
  • 1,982 posts
  • 1061

  • LocationPorto, Portugal

Posted 19 May 2012 - 02:17 PM

Works great Ryan! And no need for the redirect in this case. Thanks!
I will update the code.

#64 yellowled

yellowled

    Sr. Member

  • Members
  • PipPipPipPip
  • 183 posts
  • 117

  • LocationEutin, Germany

Posted 23 May 2012 - 02:28 PM

However, attached is a template file (basic-form.php) that is ready to use as a basic contact form with the default site profile.


Just so I don't get this mixed up: This example template is sort of a "standalone solution" for contact forms, right? It works without the the FormTemplateProcessor module?

Edit: Yes, it does. Might not be the ideal solution for anyone, but works just fine for most of my purposes. (Although a form builder would still be a neat feature.) :)

#65 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 13 August 2012 - 12:39 PM

Hello everyone,
Interesting thread! I am trying the same thing as Diogo but I need one file upload to work ... I'm getting this error
Error Call to a member function path() on a non-object (line 90 of /wire/modules/Fieldtype/FieldtypeFile.module)
Can someone help me make this FieldtypeFile work outside of the admin?
Thanks,
thomas


Edit: I almost got it. /wire/modules/Process/ProcessPageEdit/ProcessPageEdit.module holds all the secrets :)

#66 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3107

  • LocationAtlanta, GA

Posted 14 August 2012 - 07:25 AM

Can someone help me make this FieldtypeFile work outside of the admin?


I'm not sure there's enough context here to tell for sure, but the page where you are trying to add a file, try calling $page->of(false); just to make sure that the page in a state where it is ready to be saved. Also double check that the field you are calling on that page actually is a valid field name for the page. Beyond that, we might need a more specific example so I can attempt to duplicate myself.

#67 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 14 August 2012 - 07:40 AM

Thanks Ryan,
my form works so far, the only thing missing is "create page" in the InputfieldPageAutocomplete.module. Adding existing pages works fine, but creating one and adding it throws this:
Error Exception: Unknown Selector operator: '' -- was your selector value properly escaped? (in /wire/core/Selectors.php line 165)

#0 /wire/core/Selectors.php(190): Selectors->create('', '', '-1')
#1 /wire/core/Selectors.php(63): Selectors->extractString(-1)
#2 /wire/core/Pages.php(132): Selectors->__construct(-1)
#3 [internal function]: Pages->___find(-1, Array)
#4 /wire/core/Wire.php(269): call_user_func_array(Array, Array)
#5 /wire/core/Wire.php(229): Wire->runHooks('find', Array)
#6 /wire/core/Pages.php(202): Wire->__call('find', Array)
#7 /wire/core/Pages.php(202): Pages->find(-1, Array)
#8 /wire/core/Pages.php(217): Pages->findOne(-1)
#9 /wire/modules/Inputfield/InputfieldPageAutocomplete/InputfieldPageAutocomplete.module(78): Pages->get(-1)
#10 [internal function]: Inputf
The same field works fine in admin.
Any hints?

#68 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3107

  • LocationAtlanta, GA

Posted 14 August 2012 - 10:22 AM

That particular fieldtype (autocomplete) probably can't work on the front-end because it depends on an Ajax service from ProcessPageSearch. It might be possible to get it working if you are actually logged into PW admin at the time, but not sure if this is useful if you are trying to make it front-end.

#69 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 14 August 2012 - 01:45 PM

Actually it is, because I want to restrict the frontend form to registered users with a certain role anyway. Any idea why the whole select and save works, as well as creating a new page, but creating one and then saving with it selected fails?
Thanks,
thomas

#70 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3107

  • LocationAtlanta, GA

Posted 14 August 2012 - 02:08 PM

I'm not sure initially. Do you see any javascript errors or anything like that in your browser developer console? Fieldtypes like the Repeater and Autocomplete weren't ever really intended to be used outside of ProcessPageEdit, so it's possible there's some dependency in there that I'm not thinking of. It seems like the most likely possibility is a missing JS file or something which may turn up in the JS console, but hard to tell for sure.

#71 thomas

thomas

    Distinguished Member

  • Members
  • PipPipPipPip
  • 115 posts
  • 33

  • LocationKöln, Germany

Posted 15 August 2012 - 03:21 AM

Not sure what I changed but it works now! Only setTrackChanges produces wild results. Maybe it is because I don't really understand it ...?
if($input->post->submit_save) {
$edit->setTrackChanges();
	 $form->processInput($input->post);
	 foreach($form->children() as $feld) {
	  $edit->set($feld->name, $feld->value);
	 }
	 $edit->save();
  foreach(array_unique($edit->getChanges()) as $change) {
    $session->message(sprintf($this->_('Change: %s'), $change));
   }
When I trackChanges on $edit (which is the page that's being edited) I get loads of message but never one of a field that was actually changed. If I trackChanges on $form, I don't get any messages at all. I guess it has to do with the order but I just can't seem to get it right ...
Thanks for you help Ryan!
-thomas

#72 ryan

ryan

    Hero Member

  • Administrators
  • 5,771 posts
  • 3107

  • LocationAtlanta, GA

Posted 15 August 2012 - 11:50 AM

I don't think that you should need setTrackChanges. This is something that the core automatically turns on for every page it loads, so you don't need to do that unless you've got some other code elsewhere that did a setTrackChanges(false). There's also no reason to do $form->setTrackChanges(). So I'm thinking you should just remove any reference to a setTrackChanges function.

Your form may be nested, in which case your code example is only going to handle the first level of fields. Try replacing your $form->children() with $form->getAll(), which should give you all the form fields flattened.

#73 Pete

Pete

    Administrator

  • Administrators
  • 1,756 posts
  • 656

  • LocationChester, England

Posted 27 August 2012 - 02:17 PM

Hi ryan

I'm using this to send a form to an email. I've got a couple of fields that are textareas, but I'd like the email to include the newlines I enter in the textareas - currently it seems to strip them out and put them all on one line.

Is there a way to have it preserve newlines after submit?

#74 Soma

Soma

    Hero Member

  • Moderators
  • 3,186 posts
  • 1739

  • LocationSH, Switzerland

Posted 27 August 2012 - 02:56 PM

Pete have you tried adding a nl2br($value) where it's sending email @ https://github.com/r...sor.module#L166

Or with jQuery you could try set the textarea's wrap to hard. So it will convert the nl when posted and preserve them.

$('textarea').attr('wrap','hard');

Edited by Soma, 27 August 2012 - 03:16 PM.
added another option

@somartist | modules created | support me, flattr my work flattr.com


#75 adrian

adrian

    Sr. Member

  • Members
  • PipPipPipPip
  • 244 posts
  • 70

Posted 03 February 2013 - 06:31 PM

Diogo's code above taught me a lot and saved me lots of time, but I just noticed one tweak that I think should be made:

 

foreach($mypage->fields as $f) {
	$mypage->set($f->name, $form->get($f->name)->value);
}

should really be:

 

foreach($mypage->fields as $f) {
       if (!in_array($f->name, $myfields)){
		$mypage->set($f->name, $form->get($f->name)->value);
        }
}

so as to avoid "Notice: Trying to get property of non-object" errors on any fields that were excluded.

 

 

 

Also, I had to include:

 

$mypage->of(false); // turn off output formatting before setting values
$mypage->save();

I don't know whether this is something specific to my use, or whether it's just obvious and so wasn't included, but though it might help someone else.






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users