I want to add a new form to the edit customer page, so far so good, using rewrites to customer_edit_tabs i was able to add a tab and my admin form to the page. Code looks like this.
protected function _beforeToHtml()
{
$this->addTab('extraoptions', array(
'label' => Mage::helper('customer')->__('Extra options'),
'class' => 'ajax',
'url' => $this->getUrl('module/adminhtml_tabs/info', array('_current' => true)),
));
This adds my tab corrently. From there the link on the tabs controller:
public function infoAction()
{
$this->_init();
$this->getResponse()->setBody(
$this->getLayout()->createBlock('module/adminhtml_tabs_edit')->toHtml()
);;
}
This links to my form container on Block/Adminhtml/Tabs/Edit.php
class Namespace_Module_Block_Adminhtml_Tabs_Edit extends Mage_Adminhtml_Block_Widget_Form_Container{public function __construct()
{
parent::__construct();
$this->_objectId = 'id';
$this->_mode = 'edit';
$this->_blockGroup = 'module';
$this->_controller = 'adminhtml_tabs';
$this->_updateButton('save', 'label', Mage::helper('module')->__('Save'));
}
public function getHeaderText()
{
return Mage::helper('module')->__('Extra Options');
}
}
My Block/Adminhtml/Tabs/Edit/Form.php
class Namespace_Module_Block_Adminhtml_Tabs_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
public function __construct()
{
parent::__construct();
}
protected function _prepareForm()
{
$form = new Varien_Data_Form(array(
'id' => 'info_form',
'action' => $this->getUrl('module/adminhtml_tabs/save', array('id' => $this->getRequest()->getParam('id'))),
'method' => 'post',
'enctype' => 'multipart/form-data'
)
);
$fieldset = $form->addFieldset('extra_options', array('legend' => Mage::helper('module')->__('Extra Options Fieldset')));
$fieldset2->addField('extra', 'text', array(
'name' => 'zip',
'title' => Mage::helper('module')->__('extra'),
'label' => Mage::helper('module')->__('extra data'),
'maxlength' => '250',
'required' => false,
));
$form->setUseContainer(true);
}
protected function _prepareLayout()
{
return parent::_prepareLayout();
}
Everything is fine, I have a new button below the default save customer buttons, but this save button does not update the action, so if i click it, it goes to the default customer/edit/save action, it does not tell me the method does not exist which it should. My guess is that there is something wrong with the container but i have tried three tutorials with little differences to no avail, hope someone can help and even maybe someone will find my code helpful.
In this line of code:
'action' => $this->getUrl('module/adminhtml_tabs/save')
You are telling Magento to look for a module named module, a controller aliased adminhtml_tabs, and a saveAction() method within that file.
You need to figure out where you want to send the user when a save needs to be performed, and then place it there (e.g. the route to your controller->saveAction() method).
I decided to create a new button to save with a custom action. On the container:
$this->_addButton('save', array(
'label' => Mage::helper('adminhtml')->__('Save Extras'),
'onclick' => 'document.myform.submit();',
'class' => 'save',
),-1,5);
This did the trick.
Related
I am new to mangeto framework and i am learning to create a form in admin area section. However, it has been over hours that I could not figure out the error i am receiving:
Recoverable Error: Argument 1 passed to Mage_Adminhtml_Controller_Action::_addContent() must be an instance of Mage_Core_Block_Abstract, boolean given, called in /vagrant/magento/app/code/local/MasteringMagento/Example/controllers/Adminhtml/EventController.php on line 12.
The following is my Edit.php file as well as my Form.php file
Edit.php:
class MasteringMagento_Example_Adminhtml_EventController extends Mage_Adminhtml_Controller_Action{
public function indexAction(){
$this->loadLayout();
$this->_addContent(
$this->getLayout()->createBlock('example/adminhtml_event_edit'));
//go straight to the php file to render the form. otherwise this will not perfomed.
$this->renderLayout();
}
public function saveAction(){
$eventID = $this->getRequest()->getParam('event_id');
$eventModel = Mage::getModel('example/event')->load($eventID);
if($data = $this->getRequest()->getPost()){
try{
$eventModel->addData($data)->save();
Mage::getSingleton('adminhtml/session')->addSuccess(
$this->__('Your event has been saved')
);
}catch(Exception $e){
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
}
$this->_redirect('*/*/index');
}
}
}
and Form.php file:
class MasteringMagento_Example_Block_Adminhtml_Event_Edit_Form extends Mage_Adminhtml_Block_Widget_Form{
protected function _prepareForm(){
$form = new Varien_Data_Form(array('id'=>'edit_form',
'action'=>$this->getData('action'), 'method'=>'post'));
$fieldset = $form->addFieldset('base_fieldset',
array('legend'=>Mage::helper('example')->__('General Information'),
'class'=>'fieldset-wide'));
$fieldset->addField('name', 'text', array(
'name' => 'name',
'label' => Mage::helper('example')->__('Event Name'),
'title' => Mage::helper('example')->__('Event Name'),
'required' => true
));
$dateFormatIso = Mage::app()->getLocale()->getDateFormat(
Mage_Core_Model_Locale::FORMAT_TYPE_SHORT);
$fieldset->addField('start', 'date', array(
'name' => 'start',
'format' => $dateFormatIso,
'image' => $this->getSkinUrl('images/grid-cal.gif'),
'label' => Mage::helper('example')->__('Start Date'),
'title' => Mage::helper('example')->__('Start Date'),
'required' => true
));
$fieldset->addField('end', 'date', array(
'name' => 'end',
'format' => $dateFormatIso,
'image' => $this->getSkinUrl('images/grid-cal.gif'),
'label' => Mage::helper('example')->__('End Date'),
'title' => Mage::helper('example')->__('End Date'),
'required' => true
));
$form->setUseContainer(true);
$this->setForm($form);
return parent::_prepareForm();
}
}
The error i think is from my Controller. However, if i direct the url link to the form, it will display. But if i direct to its container which is Edit.php, the error above would occurs:
class MasteringMagento_Example_Adminhtml_EventController extends Mage_Adminhtml_Controller_Action{
public function indexAction(){
$this->loadLayout();
$this->_addContent(
$this->getLayout()->createBlock('example/adminhtml_event_edit'));
//go straight to the php file to render the form. otherwise this will not perfomed.
$this->renderLayout();
}}
This is my config.xml. I did include the base class for Magento Blocks:
<blocks>
<example>
<class>MasteringMagento_Example_Block</class>
</example>
</blocks>
Please help me to identify the problem. Thanks
createBlock() is an abstract factory pattern for Blocks inside of Magento. Whenever Magento cannot resolve a factory class from this method, a boolean is returned... which is the case in your example, as the error message says.
Check your class MasteringMagento_Example_Block_Adminhtml_Event_Edit for spelling, casing, or class related errors. Also ensure that your class file is located at app/code/local/MasteringMagento/Example/Block/Adminhtml/Event/Edit.php.
In magento, every admin form block is loaded first by a form container.
Here, you call MasteringMagento_Example_Block_Adminhtml_Event_Edit class :
$this->getLayout()->createBlock('example/adminhtml_event_edit')
This class, located in app/code/local/MasteringMagento/Example/Block/Adminhtml/Post/Edit.php, should look to something like this :
<?php
/**
* MasteringMagento_Example_Block_Adminhtml_Post_Edit
*/
class MasteringMagento_Example_Block_Adminhtml_Post_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
{
public function __construct()
{
// $this->_objectId = 'id';
parent::__construct();
$this->_blockGroup = 'example';
$this->_controller = 'adminhtml_post';
$this->_mode = 'edit';
$modelTitle = $this->_getModelTitle();
$this->_updateButton('save', 'label', $this->_getHelper()->__("Save $modelTitle"));
$this->_addButton('saveandcontinue', array(
'label' => $this->_getHelper()->__('Save and Continue Edit'),
'onclick' => 'saveAndContinueEdit()',
'class' => 'save',
), -100);
$this->_formScripts[] = "
function saveAndContinueEdit(){
editForm.submit($('edit_form').action+'back/edit/');
}
";
}
protected function _getHelper(){
return Mage::helper('example');
}
protected function _getModel(){
return Mage::registry('exemple_youmodel');
}
protected function _getModelTitle(){
return 'Post';
}
public function getHeaderText()
{
$model = $this->_getModel();
$modelTitle = $this->_getModelTitle();
if ($model && $model->getId()) {
return $this->_getHelper()->__("Edit $modelTitle (ID: {$model->getId()})");
}
else {
return $this->_getHelper()->__("New $modelTitle");
}
}
/**
* Get URL for back (reset) button
*
* #return string
*/
public function getBackUrl()
{
return $this->getUrl('*/*/index');
}
public function getDeleteUrl()
{
return $this->getUrl('*/*/delete', array($this->_objectId => $this->getRequest()->getParam($this->_objectId)));
}
}
As you can see, all your buttons are set in the __construct() method.
Hope it helps.
I am trying to set up an edit form for an entity (Place) in my app. For this purpose I have written the form (PlaceForm), fieldset (PlaceFieldset), .phtml pages and functions in the controller. Since I am new in zf2, I have concentrated on the tutorlias on their homepage. I have seen that from validation is provided by the framework but in my case it is not necessary. None of the fields added in the fieldset have not the required attribute, however when I submit the form under all empty fields I get the message "Value is required and can't be empty" although it is actually not required. I do not want to create a wall of code in this question, so I will start with the function from the controller. If there is someone who would like to help me with this issue, just let me know and I will update any other part of the code (form, fieldset etc.) Thx in advance.
...
public function editPlaceAction() {
$id = $this->params()->fromRoute('id');
$uiServiceProvider = $this->getServiceLocator()->get('FamilyTree\Service\UiServiceProvider');
$placeArray = $uiServiceProvider->fetchSinglePlaceById($id);
$place = new Places($placeArray);
$form = new PlaceForm();
$form->bind($place);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
var_dump($place);
}
}
$view = new ViewModel(array(
'form' => $form,
'title'=>"Edit place"
));
$view->setTemplate("family-tree/family-tree-maintenance/editPlace");
return $view;
}
...
and here you can see how my Fieldset looks like
<?php
namespace Places\Form;
use Zend\Form\Fieldset;
class PlaceFieldset extends Fieldset {
public function __construct() {
parent::__construct('place');
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
));
$this->add(array(
'name' => 'name',
'type' => 'Text',
'options' => array(
'label' => 'Name',
),
));
$this->add(array(
'name' => 'admUnit1',
'type' => 'Text',
'options' => array(
'label' => 'AdmUnit1',
),
));
}
}
I've created an admin module based off of the tutorial here. I'm attempting to change two of my form inputs to wysiwyg editors based off of information found here. However, whenever I load the edit page I get an error Call to a member function setCanLoadTinyMce() on a non-object. $this->getLayout()->getBlock('head') var_dumps to false.
Namespace/Slides/Block/Adminhtml/Slide/Edit.php looks as follows
class Namespace_Slides_Block_Adminhtml_Slide_Edit
extends Mage_Adminhtml_Block_Widget_Form_Container
{
protected function _prepareLayout()
{
parent::_prepareLayout();
if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) {
$this->getLayout()->getBlock('head')->setCanLoadTinyMce(true);
}
}
protected function _construct()
{
//... Construction stuff
}
}
Namespace/Slides/Block/Adminhtml/Slide/Edit/Form.php
class Cfw_Slides_Block_Adminhtml_Slide_Edit_Form
extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
//...Do some things first, like create the fieldset..
//Add the editable fields
$this->_addFieldsToFieldset($fieldset, array(
'foreground_image' => array(
'label' => $this->__('Foreground Image'),
'input' => 'image',
'required' => false,
),
'background_image' => array(
'label' => $this->__('Background Image'),
'input' => 'editor',
'required' => true,
'config' => Mage::getSingleton('cms/wysiwyg_config')->getConfig(),
'wysiwyg' => true,
),
'description' => array(
'label' => $this->__('Text Overlay'),
'input' => 'editor',
'required' => false,
'config' => Mage::getSingleton('cms/wysiwyg_config')->getConfig(),
'wysiwyg' => true,
)
));
return $this;
}
protected function _addFieldsToFieldset(
Varien_Data_Form_ElementFieldset $fieldset, $fields)
{
$requestData = new Varien_Object($this->getRequest()->getPost('slideData'));
foreach ($fields as $name => $_data) {
if ($requestValue = $requestData->getData($name)) {
$_data['value'] = $requestValue;
}
//Wrap all fields with slideData group
$_data['name'] = "slideData[$name]";
//Generally, label and title are always the same
$_data['title'] = $_data['label'];
//If no new value exists, use the existing slide data.
if (!array_key_exists('value', $_data)) {
$_data['value'] = $this->_getSlide()->getData($name);
}
//Finally, call vanilla funcctionality to add field.
$fieldset->addField($name, $_data['input'], $_data);
}
return $this;
}
}
I'm not sure if you need it, but here's my file structure as well
Namespace
-Slides
--Block
---Adminhtml
----Slide
-----Edit
------Form.php
-----Edit.php
-----Grid.php
----Slide.php
--controllers
---Adminhtml
----SlideConroller.php
--etc
---config.xml
--Helper
---Data.php
--Model
---Resource
----Slide
-----Collection.php
----Slide.php
---Slide.php
--sql
---namespace_slides_setup
----install-0.0.1.php
The issue is that Magento cannot find your head block.
Instead of using:
$this->getLayout()->getBlock('head')->setCanLoadTinyMce(true);
Try calling it like this:
Mage::app()->getLayout()->getBlock('head')->setCanLoadTinyMce(true);
If that doesn't work, it's a different issue but the problem is still that Magento can't find the head block.
I imagine you no longer need a solution for this, but I ran into the same issue using the same tutorial that you did.
The 'head' block (and thus setCanLoadTinyMce()) was unavailable in the Edit.php and the Form.php via the _prepareLayout() function.
The 'head' block was available in the controller(SlideController.php in your case) between $this->loadLayout() and $this->renderLayout within the editAction() function.
In SlideController.php change
$this->loadLayout()
->_addContent($brandBlock)
->renderLayout();
to
$this->loadLayout() ;
$this->_addContent($brandBlock);
$this->getLayout()->getBlock('head')->setCanLoadTinyMce(true);
$this->renderLayout();
I am working on an edit screen for my grid row. This is what I have so far for this form:
<?php
class Intellibi_Integration_Block_Adminhtml_Manageasendiapickinglists_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form();
$this->setForm($form);
$fieldset = $form->addFieldset('integration_form', array(
'legend' => Mage::helper('integration')->__('Asendia Pick Information')
));
$fieldset->addField('order_number', 'label', array(
'label' => Mage::helper('integration')->__('Order Number'),
'name' => 'order_number'
));
// snipped
$fieldset->addField('pick_status', 'select', array(
'required' => false,
'class' => 'required-entry',
'label' => Mage::helper('integration')->__('Pick Status'),
'name' => 'pick_status',
'values' => Mage::getSingleton('ibi/asendiapickstatus')->getOptionArray(),
'readonly' => 'readonly'
));
// snipped
return parent::_prepareForm();
}
}
This produces the following output in the admin backend:
What I would like to do is change the pick_status column from a select to a label. When I do this, instead of showing the status value "New" it shows the array index like this:
My option array for asendiapickstatus is defined like this in my model:
class Intellibi_Integration_Model_Asendiapickstatus extends Varien_Object
{
const PICK_STATUS_NEW = 1;
const PICK_STATUS_SENT = 2;
const PICK_STATUS_SHIPPED = 3;
static public function getOptionArray()
{
return array(
self::PICK_STATUS_NEW => Mage::helper('integration')->__('New'),
self::PICK_STATUS_SENT => Mage::helper('integration')->__('Sent'),
self::PICK_STATUS_SHIPPED => Mage::helper('integration')->__('Shipped')
);
}
}
So my question is; on the edit form fieldset builder, how do I show the dropdown field "pick_status" value, rather than the current index it's at? So the output will say "New" instead of "1" as shown above. Will I need a custom renderer?
I've solved it like this (with a custom form rendered element):
Added custom fieldset type
$fieldset->addType('pickstatus', 'Intellibi_Integration_Block_Adminhtml_Manageasendiapickinglists_Edit_Tab_Form_Renderer_Fieldset_Pickstatus');
Used the fieldset like this
$fieldset->addField('pick_status', 'pickstatus', array(
'label' => Mage::helper('integration')->__('Pick Status'),
'name' => 'pick_status',
));
Coded the rendered like this
class Intellibi_Integration_Block_Adminhtml_Manageasendiapickinglists_Edit_Tab_Form_Renderer_Fieldset_Pickstatus extends Varien_Data_Form_Element_Abstract
{
protected $_element;
public function getElementHtml()
{
// Load Pick Status
$pick_status = (int)$this->getValue();
$pick_status_list = Mage::getSingleton('ibi/asendiapickstatus')->getOptionArray();
// Finish
return array_key_exists($pick_status, $pick_status_list) ? $pick_status_list[$pick_status] : 'Unknown';
}
}
And it renders like this
I have controller with an add action.
public function add() {
$this->layout = 'manage';
$this->set($this->Restaurant->fetchRelatedData());
if ($this->request->is('post')) {
$this->Restaurant->create();
if ($this->Restaurant->save($this->request->data)) {
$this->Session->setFlash('ok!');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Error!');
}
}
}
View for this action created with Form and Js helpers:
echo $this->Form->create('Restaurant');
// some fields
echo $this->Form->input('district_id', array('label' => 'District'));
echo $this->Form->input('street_id', array('label' => 'Street'));
// other fields
echo $this->Form->end(array('label' => 'Add'));
$this->Js->get('#RestaurantDistrictId')->event('change',
$this->Js->request(array(
'controller'=>'streets',
'action'=>'getByDistrict'
), array(
'update'=>'#RestaurantStreetId',
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(array(
'isForm' => true,
'inline' => true
))
))
);
Js helper shows list with streets that are in choosen district.
StreetsController -> getByDistrict action:
public function getByDistrict(){
$district_id = $this->request->data['Restaurant']['district_id'];
$streets = $this->Street->find('list', array(
'conditions' => array('Street.district_id' => $district_id),
'fields' => array('street'),
'order' => array('Street'),
'recursive' => -1,
));
$this->set('streets', $streets);
$this->layout = 'ajax';
}
Everything worked fine until I added the administrative prefix to this action.
If action is named public function add() – all things works.
If action is named *public function admin_add()* – Js helper stops updating streets list on district change.
I'm not 100% sure on this, but I believe that the JS helper is preserving the admin prefix when it makes the AJAX request. When in add() it would call getByDistrict(). When in admin_add() it would call admin_getByDistrict(). Try passing 'admin' => false into Js->request.