Jump to content

Formbuilder: Problem with page select field


Xonox
 Share

Recommended Posts

Hi,

I'm having a problem with a page selection field. I have the following tree set up:

Activities
   - Activity 1
   - Activity 2
   - Activity 3
   - Activity 4

So I created a form where you can select one of the activities on which you would like to participate.

For usability purposes, the form is inserted in each Activity page, so that the user doesn't have to click to get to a form.

I have two problems (let's say the user is inside the "Activity 2" page);

1. Inside the form, where the user can select the activity, the current page is not listed, so the user can select "Activity 1", "Activity 3" and "Activity 4", but not the one in which he is. This one might be a bug.

2. It would be nice that the activity in which he is - Activity 2 - Would be selected by default.

Is there any way that I can accomplish this without a custom markup form?

Thank you.

Link to comment
Share on other sites

On 11/5/2018 at 5:14 PM, elabx said:

You can probably do this within the InputfieldPage::getSelectablePages hook, that way you can tweak the selectable pages, I'd also try tweaking the value attribute through another field, honestly can't think of the details right now but hope I have given you a hint on a possible solution. 

Hi @elabx,

Thanks for your reply. I really need some help here, working with Hooks.

First, watching the function you showed me, I believe that the responsible bit for not having the self page in the selector is the last part. So it's not a bug, but a feature (not sure why). This are the lines I need to override.:

if($children && $children->has($page)) {
	$children->remove($page); // don't allow page being edited to be selected
}

 

I was playing around with the hooks but I couldn't figure it out. Form builder doesn't have a InputFieldPage Hook, so how am I supposed to hook into it?

The code below must be completely wrong, my apologies, but I'm completely lost here (I have this inside _init.php):

if($page->template == 'activity') {

	// This hook will make sure that the list of pages include self page
	$this->addHookBefore('InputfieldPage::getSelectablePages', function($event) {
		$children = $pages->get('parent=1066');
		return $children;
	});

	$activity_form = $forms->render('activity_form');

}

Can someone point me to the right direction? Thanks!

Alternative

When rendering the select field, add current page and make it selected. Is this possible?

Link to comment
Share on other sites

33 minutes ago, Xonox said:

Alternative

When rendering the select field, add current page and make it selected. Is this possible?

Thinking about this alternative. This might work better.

So now I have a working code inside _init.php:

// Activity form
if($page->template == 'activity') {

	$forms->addHookBefore('FormBuilderProcessor::renderReady', function($e) {

		$form = $e->arguments(0);
		if($form->name == 'activity_form') {

			// Get Atividade field
			$inputfield = $form->getChildByName('atividade');
			// I NEED TO INSERT A SELECTED OPTION HERE
			// something something = $page->id;

		}

	});

	$activity_form = $forms->render('activity_form');

}

Getting close. Can someone help?

  • Like 1
Link to comment
Share on other sites

40 minutes ago, Xonox said:

Form builder doesn't have a InputFieldPage Hook, so how am I supposed to hook into it?

Form buiilder is awesome because it does all it's heavy lifting with the same Inputfield classes you use in page edits, so it is indeed an InputfieldPage!

Assuming this is renderd in an iframe try this code (try it in ready.php, I'm really not sure if its the same as doing it on init.php):

$wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) {
    $log = wire('log');

    //The default PageArray getting selected through your field config
    $defaultSelection = $event->return;
    
    //This is passed through a parameter! 
    //$forms->embed('form-name', ['contextPage' => $page])
    $contextPage = $input->get->contextPage;

    //This would be form-builder page, where it actually renders! 
    //which is not the place the iframe is rendered :)
    $page = $event->arguments('page');
    
    $log->save("debug-pagefield", $page->name);
    $log->save("debug-pagefield", $defaultSelection);
});

 

Link to comment
Share on other sites

4 minutes ago, Xonox said:

Thinking about this alternative. This might work better.

So now I have a working code inside _init.php:


// Activity form
if($page->template == 'activity') {

	$forms->addHookBefore('FormBuilderProcessor::renderReady', function($e) {

		$form = $e->arguments(0);
		if($form->name == 'activity_form') {

			// Get Atividade field
			$inputfield = $form->getChildByName('atividade');
			// I NEED TO INSERT A SELECTED OPTION HERE
			// something something = $page->id;

		}

	});

	$activity_form = $forms->render('activity_form');

}

Getting close. Can someone help?

Hahah of course! This is super valid, maybe set the value field with the addOption() removeOption() methods (I think what is actually being rendered is an InputfieldSelect, sorry for the misguidance?

https://github.com/processwire/processwire/blob/341342dc5b1c58012ae7cb26cffe2c57cd915552/wire/modules/Inputfield/InputfieldSelect.module#L173

Link to comment
Share on other sites

39 minutes ago, elabx said:

Hahah of course! This is super valid, maybe set the value field with the addOption() removeOption() methods (I think what is actually being rendered is an InputfieldSelect, sorry for the misguidance?

So close and yet so far!

if($form->name == 'activity_form') {

	// Get Atividade field
	$inputfield = $form->getChildByName('atividade');
	$page = wire('page');
	$inputfield->addOption($page->id, $page->title, array('selected'));

}

Two problems:

1 - $page = wire('page'); is this the best way to have access to the page id and title inside the hook? Is there a performance issue?

2 - Error on addOption:

Error: Exception: Method InputfieldPage::addOption does not exist or is not callable in this context (in E:\WebServer\clinicadasconchas.pt\wire\core\Wire.php line 519)

#0 E:\WebServer\clinicadasconchas.pt\wire\core\Wire.php(386): ProcessWire\Wire->___callUnknown('addOption', Array)
#1 E:\WebServer\clinicadasconchas.pt\wire\core\WireHooks.php(723): ProcessWire\Wire->_callMethod('___callUnknown', Array)
#2 E:\WebServer\clinicadasconchas.pt\wire\core\Wire.php(442): ProcessWire\WireHooks->runHooks(Object(ProcessWire\InputfieldPage), 'callUnknown', Array)
#3 E:\WebServer\clinicadasconchas.pt\wire\core\Wire.php(445): ProcessWire\Wire->__call('callUnknown', Array)
#4 E:\WebServer\clinicadasconchas.pt\site\assets\cache\FileCompiler\site\templates\_init.php(31): ProcessWire\Wire->__call('addOption', Array)
#5 E:\WebServer\clinicadasconchas.pt\wire\core\WireHooks.php(813): ProcessWire\TemplateFile->{closure}(Object(ProcessWire\HookEvent))
#6 E:\WebServer\clinicadasconchas.pt\wire\core\Wire.php(442): ProcessWire\WireHooks->ru

It looks like it is a InputfieldPage field, and this doesn't have addOption method.

Link to comment
Share on other sites

Bingo!

In case someone needs it:

// Activity form
if($page->template == 'activity') {

	$forms->addHookBefore('FormBuilderProcessor::renderReady', function($e) {

		$form = $e->arguments(0);
		if($form->name == 'activity_form') {

			$page = wire('page'); // IS THIS RIGHT?
			$selected = array(); // IS THIS RIGHT?
			$selected['selected'] = 'selected'; // IS THIS RIGHT?

			// Get Atividade field
			$inputfield = $form->getChildByName('atividade'); // Get InputfieldPage
			$select_field = $inputfield->getInputField(); // Get the correspondent InputfieldSelect
			$select_field->addOption($page->id, $page->title, $selected); // Add current page as selected option
		}

	});

	$activity_form = $forms->render('activity_form');

}

Thanks for your help @elabx, it made all the difference!

  • Like 2
Link to comment
Share on other sites

I'd love if someone could come and give an opinion on why InputfieldPage has a getInputfield() method? I though that object was an InputfieldPage, not a Fieldtype. I'll have to take a look with Tracy Debugger later. 

Link to comment
Share on other sites

11 hours ago, elabx said:

I'd love if someone could come and give an opinion on why InputfieldPage has a getInputfield() method?

InputfieldPage can be seen as a "layered" inputfield. InputfieldPage itself takes care of the basic logic (processing input, rendering contents etc.) but the ui input itself is delegated to another inputfield type (plain select, ASM select, page autocomplete etc.). Since all of the page related logic (outside specific page inputs like autocomplete or pagelistselect) is inside InputfieldPage, the "real" input modules themselves can be used to input other things besides PW pages too since all they have to deal with are options with values and labels.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • 2 years later...

This post was really useful for me when outputting a preselected value within the form so thank you @Xonox and @elabx.

In our case, we are showing different course pages that each include an enquiry form created with formbuilder (embed c option). Using your tips above, the form will preselect the course of interest based on the course page you are viewing. This all displays perfectly on the front end.

One thing I've noticed though is that this value doesn't pass through to the form entries or the email that is automatically sent to the administrators once it is submitted. It does work when the selected course is different to the course page that is being viewed. I've limited experience with hooks and just wondered if anyone knew of a way to pass the course name into the course entry though, which would be a little easier for the client.

I've put a temporary fix in place that involves creating a hidden form field that stores the current page name, so administrators can at least get a sense of what course page the form was submitted and put two and two together, when the pre-selected value is the actual course page being viewed.

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...