Silverstripe Multiple Userforms on one page
Asked Answered
H

3

5

I am trying to create a single page that will display multiple userforms in a tabbed view. For example basic contact form, request a quote form etc.

I thought I could make a new page type and loop through the children to display the forms, but the $Form variable isn't rendering the form.

<% loop $Children %>
   <div>
     <h2>$Title</h2>
     $Form
   </div>
<% end_loop %>

Am I missing something here, or is there a different way to render a form using a its ID in a template file?

Heckle answered 19/1, 2016 at 22:17 Comment(2)
You are iterating over DataObjects on that context, not the controller classes and their methods. Also getting it to works is somewhat tricy: #30404967Perth
Depending on the forms and their "functionalities" it might be more "easier" just to add placeholders for them on the loops and use js to replace the placeholders with an iframe that expands to the form content size.Perth
G
4

You could try the following.

Create a function in your page holder controller to get the form from a specific child (must be a UserDefinedForm page). To do this you'll need to create the controller of this child page.

public function ChildForm($pageID) {
  $page = UserDefinedForm::get()->byID($pageID);
  $controller = UserDefinedForm_Controller::create($page);
  return $controller->Form();
}

afterwards you'll call this function in your loop and pass the current child id to it

<% loop $Children %>
   <div>
     <h2>$Title</h2>
     $Top.ChildForm($ID)
   </div>
<% end_loop %>

This should (code is untested) return the forms you want.

Graduation answered 21/1, 2016 at 15:45 Comment(0)
Y
3

The problem at play here is the difference between the DataObject/Page and the Controller. Looping over $Children returns you a DataObject whereas the Form function and template variable are part of UserDefinedForm's controller.

The other answer shows one working solution however it has some hair on it:

  • Jumping scope to your controller to pass an ID to get your form
  • Additional DB query
  • Requires all the child pages to be of type UserDefinedForm

We can implement a more generic solution that removes some of those elements and making your code a little more maintainable.

Take the following which would be added to the Page class (not the controller):

function getInLoopForm() {
    if (in_array('UserDefinedForm', $this->ClassAncestry)) {
        $controllerName = $this->ClassName . '_Controller';
        $controller = $controllerName::create($this);
        if ($controller->hasMethod('Form')) {
            return $controller->Form();
        }
    }
    return false;
}

The first part of that checks whether the current object has UserDefinedForm in its class ancestry. If it is, we then create the appropriate controller and return the form.

Your template code would look like this instead:

<% loop $Children %>
   <div>
     <h2>$Title</h2>
     $InLoopForm
   </div>
<% end_loop %>

This solution is generic for three reasons:

  • In our getInLoopForm function, the value "UserDefinedForm" can be replaced with any class that extends Page. It could even be brought out to a YML value if you were so inclined.
  • For SilverStripe, controller names for pages must match "{PageClassName}_Controller" so we can abuse that by working out the controller name dynamically. This allows for you to extend UserDefinedForm and its controller and we can still call the right function.
  • You only require your DataObject to access the form, you don't need your own controller.
Yellowthroat answered 18/7, 2016 at 2:44 Comment(1)
Looks like a great solution. How would this work in Silverstripe 4 when you have to use the namepaces? thanks in advance.Increate
I
0

For SS 4 there is a small code change needed:

public function getInLoopForm() {
    if (in_array('SilverStripe\UserForms\Model\UserDefinedForm', $this->ClassAncestry)) {
        $controller = UserDefinedFormController::create($this);
        if ($controller->hasMethod('Form')) {
            return $controller->Form();
        }
    }
    return false;
}
Increate answered 14/3, 2018 at 20:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.