Magento – How to create forms for a custom adminhtml module

adminformadminhtmlformsmagento-1.8

Synopsis

I have a custom module where I would like to upload files to products and optionally store a name/label, description and visibility options for each file.

I am stuck at creating my own form, i've tried created a block and searched through the Varien_ source and i'm completely lost and confused with no articles or tutorials on how to create a basic form and render it.

I'm looking for some links/references to useful resources about:

  • Creating a form, fieldsets and fields;
  • Applying validation rules and running said validation;

My attempt

I have tried to create a basic form to display something, and i don't get any response.

Controller

<?php
class Vendor_ProductUploader_Adminhtml_Product_Uploader_AttachmentController
    extends Mage_Adminhtml_Controller_Action
{

    # ...

    public function newAction()
    {
        $params = $this->getRequest()->getParams();
        $post   = $this->getRequest()->getPost();

        // test something.
        $response = $this->getLayout()
            ->createBlock('vendor_productuploader/adminhtml_attachment_form')
            #->setTemplate('vendor/productuploader/form.phtml') # this is done in _construct()
            ->toHtml();

        try {
            if (! $post) {
                Mage::throwException($this->__('Invalid stuffs'));
            }

            Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Uploaded!'));
        } catch (Exception $e) {
            Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
        }

        $this->getResponse()->setBody($response);
        #$this->_redirect('*/*/grid', array('_current' => true));
    }

}

./Vendor/ProductUploader/Block/Adminhtml/Attachment/Form.php

class Vendor_ProductUploader_Block_Adminhtml_Attachment_Form
    extends Mage_Adminhtml_Block_Widget_Form
{

    public function _construct()
    {
        parent::_construct();
        # XXX: What does this template do? Surely the getHTml() would generate the source?
        //$this->setTemplate('vendor/productuploader/form.php');
    }

    protected function _prepareForm()
    {
        # XXX: create form.
        $form = new Varien_Data_Form(array(
            'id'     => 'edit_form',
            'method' => 'post',
            'action' => $this->getUrl('*/*/new', array('_current' => true)),
        ));

        // No idea why i need to do this, but a form instance doesn't exist.
        $this->setForm($form);

        # XXX: create fieldset.

        $fieldset = $form->addFieldset('my_fieldset', array('legend' => 'test'));

        # XXX: create fields to fieldset.

        $fieldset->addField('my_field', 'text', array(
            'label' => 'My Label',
            'name'  => 'some_field',
            'required' => true,
            'value' => 'hello',
        ));

        return parent::_prepareForm();
    }
}

After @Vladimir's answer, I have amended my code. I'm still not receiving any response from the controller though.

Controller

class Vendor_ProductUploader_Adminhtml_Product_Uploader_AttachmentController
    extends Mage_Adminhtml_Controller_Action
{

    # ...

    public function newAction()
    {
        $params = $this->getRequest()->getParams();
        $post   = $this->getRequest()->getPost();

        $this->loadlayout();
        $this->_addContent($this->getLayout()->createBlock('vendor_productuploader/adminhtml_form_attachment'));
        $this->renderLayout();

        die;
    }

    # ...

}

Form Container

class Vendor_ProductUploader_Block_Adminhtml_Form_Attachment
    extends Mage_Adminhtml_Block_Widget_Form_Container
{
    public function __construct()
    {
        parent::__construct();
        $this->_objectId   = 'my_object_id';
        $this->_blockGroup = 'vendor_productuploader';
        $this->_controller = 'adminhtml';
        $this->_mode       = 'form';
    }

    public function getHeaderText()
    {
        return Mage::helper('vendor_productuploader')->__('Form Container');
    }
}

Form

class Vendor_ProductUploader_Block_Adminhtml_Form_Form
    extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _construct()
    {
        parent::_construct();

        $form = new Varien_Data_Form(array(
            'id'      => 'edit_form',
            'method'  => 'post',
            'enctype' => 'multipart/form-data',
            'action'  => $this->getUrl('*/*/new', array('_current' => true)),
        ));

        $form->setUseContainer(true);
        $this->setForm($form);

        return $this;
    }

    protected function _prepareForm()
    {
        $fieldset = $this->getForm()
            ->addFieldset('my_el_form_fs111', array(
                'legend' => Mage::helper('vendor_productuploader')->__('Legend Text')
            ));

        $fieldset->addField('title', 'text', array(
            'label'    => 'El Label',
            'name'     => 'el_name',
            'class'    => 'el_class--name',
            'required' => true,
        ));

        return parent::_prepareForm();
    }
}

Best Answer

To create your own form you need the following:

In your controller you need to load the Form Container Widget:

class Vendor_ProductUploader_Adminhtml_Product_Uploader_AttachmentController
extends Mage_Adminhtml_Controller_Action {

public function newAction() {
    $this->loadLayout()->_addContent($this->getLayout()->createBlock('vendor_productuploader/adminhtml_attachment'))->renderLayout();
}

Next you need to create the Form Container (this one is missing in your code posted above):

class Vendor_ProductUploader_Block_Adminhtml_Attachment
    extends Mage_Adminhtml_Block_Widget_Form_Container {

public function __construct() {
    parent::__construct();

    $this->_blockGroup = 'vendor_productuploader';
    $this->_mode = 'attachment';
    $this->_controller = 'adminhtml';

}

public function getHeaderText() {
    return Mage::helper('vendor_productuploader')->__("My form header");
}

public function getBackUrl() {
    return $this->getUrl('*/*/');
}

The last item you need is in your form, at the end you need to set the form you created with:

$this->setForm($form);
Related Topic