3

I have some custom routes in my system:

---
Name: mysiteroutes
---
Director:
  rules:
    'create//$Action': 'CreateController'

Which has a custom controller to create a form:

class CreateController extends Page_Controller{

    private static $allowed_actions = array(
        'submit'
    );

    public function link($action = null) {
        return $this->join_links('create/', $action);
    }

    public function index() {
        $form = Form::create(
            $this,
            '',
            FieldList::create(
                TextField::create('Name', 'Name'),
                $upload = new UploadField('Upload', 'Upload')
            ),
            FieldList::create(
                FormAction::create('submit', 'Submit')->setAttribute('class', 'btn btn-success')
            ),
            RequiredFields::create('Name')
        );
        if($this->request->isPost()) return $form;
        return $this->customise(array('Form'=>$form))->renderWith(array("Create", "Page"));     
    }

    public function submit($data, $form = null) {
        $params = $this->getRequest()->params();
        var_dump($params);
    }
}

When I try and upload something it calls Field() on my controller and then fails as it's not there. I can add it and it calls it correctly however I have no idea what to put in it. I've looked through the Field() function in UploadField.php however there is a lot of code there which I probably shouldn't just copy.

How should I manage the upload of the file in my custom controller or can I forward it to the core framework somehow?

Rudiger
  • 6,749
  • 13
  • 51
  • 102

1 Answers1

1

UploadField expects to have a route based on the Form name, in your case ''. If you would change the name of the form to form it would call form/field/Upload/upload. What this does is get the form, then get the field with the name Upload and call the method upload on that class.

Unfortunately, the way you are using the form (which I showed you in an earlier answer :( ) does not support this.

We could solve it like this;

CreateController

class CreateController extends Page_Controller
{
    private static $allowed_actions = [
        'form'
    ];

    public function link($action = null) 
    {
        return $this->join_links('create', $action);
    }

    public function index()
    {
        return $this->renderWith(array("Create", "Page"));     
    }

    public function form()
    {
        return UploadForm::create($this, 'form', 'submit');
    }

    public function submit($data, $form = null)
    {
        $params = $this->getRequest()->params();
        var_dump($params);
    }
}

Form

// create an extra class for the form to keep your controller clean
class UploadForm extends Form
{
    public function __construct($controller, $name, $action)
    {
        $fields = FieldList::create(
            TextField::create('Name', 'Name'),
            UploadField::create('Upload', 'Upload')
        );

        $actions = FieldList::create(
            FormAction::create($action, 'Submit')
                ->setAttribute('class', 'btn btn-success')
        );

        $validator = RequiredFields::create('Name');

        parent::__construct($controller, $name, $fields, $actions, $validator);
    }
}
Fatal Error
  • 1,024
  • 6
  • 12
  • Thanks and sorry for you answering all my questions. There isn't much detail about custom routing with forms, or with SilverStripe in general which is a shame because it's a great framework. – Rudiger Nov 28 '16 at 08:54
  • No problem, I'm happy to help. Was this answer helpfull for you? – Fatal Error Nov 28 '16 at 10:16
  • It's at work so I'll have to test later, I'm sure it will be but have to check. – Rudiger Nov 28 '16 at 20:07
  • One thing I'm lost with, how does the template know to render the `form()`? Is it because the template has $Form it looks for a function called `form` in the parent controller? – Rudiger Nov 29 '16 at 00:05
  • 1
    That's because we return `$this` (the controller) in the index method. Because a Controller is also an instance of `ViewableData`, all the methods on the controller are available in the template. Note that when you call `$this->customise(array('Form' => $form))`, only the `$Form` is available in the template. – Fatal Error Nov 29 '16 at 07:24