I've a fully working backend page with a grid and a corresponding form to edit the changes on the corresponding model. I added a new field on the table, bit type, as it will answer to a yes/no configuration option from the user. I added the checkbox on both grid and form.
My problem is that after a couple of hours of searching and trying different approaches I can not set the checkbox checked value both on the grid and the form reading the corresponding field from the database. Also when I click on save on the form the value corresponding to the checkbox is always saved with 1. Everything else on the grid and the form works as it should. I have read here, here, here, here and some more sites and SO questions/answers but still no clue on what I'm doing wrong. Some solutions recommend using a combo box with YES/NO options, but I want a checkbox, can't be so difficult.
Grid code inside the function _prepareColumns():
protected function _prepareColumns() {
...
$this->addColumn('banner_gral', array(
'header' => Mage::helper('banners')->__('General'),
'align' => 'center',
'index' => 'banner_gral',
'type' => 'checkbox',
'values' => $this->getBannerGral()==1 ? 'true' : 'false',
));
...
}
public function __construct()
{
parent::__construct();
$this->setId('bannersgrid');
$this->setDefaultSort('bannerid');
$this->setDefaultDir('asc');
$this->setSaveParametersInSession(true);
$this->setUseAjax(true);
}
public function getGridUrl()
{
return $this->getUrl('*/*/grid', array('_current'=>true));
}
protected function _prepareCollection()
{
$collection = Mage::getModel('banners/bannersadmin')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
Form code to add the checkbox inside the function _prepareForm():
protected function _prepareForm()
{
$id = $this->getRequest()->getParam('id');
$params = array('id' => $this->getRequest()->getParam('id'));
if (Mage::registry('banners_data')->getdata()) {
$data = Mage::registry('banners_data')->getdata();
}
elseif (Mage::getSingleton('adminhtml/session')) {
$data = Mage::getSingleton('adminhtml/session')->getdata();
Mage::getSingleton('adminhtml/session')->getdata(null);
}
else {
$data = array();
}
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save', $params),
'method' => 'post',
'enctype' => 'multipart/form-data',
));
...
$fieldset->addField('banner_gral', 'checkbox', array(
'label' => Mage::helper('banners')->__('Is general'),
'name' => 'banner_gral',
'class' => 'banner_gral',
'checked' => $this->getBannerGral()==1 ? 'true' : 'false',
'onclick' => 'this.value == this.checked ? 1 : 0',
'note' => Mage::helper('banners')->__('blablablabla'),
'tabindex' => 2
));
...
}
On the saveAction() of my form I have:
$campaign->setbanner_gral(!empty($data['banner_gral']));
In your controller saveAction() when saving the checkbox data do
$banner_gral = isset($your_form_Data['banner_gral']) ? 1 : 0;
For Grid and Form Page
In your controller you should have Mage::register(...)->getData() or Mage::register(...)
public function editAction()
....
Mage::register('example_data', $model);
On your form _prepareForm()
$model = Mage::registry('example_data'); // NOTE registry('example_data'); NOT registry('example_data')->getData();
$fieldset->addField('entire_range', 'checkbox', array(
....
'checked' => $model->getBannerGral()==1 ? 'true' : 'false',
......
))
see http://www.magentocommerce.com/boards/viewthread/20536/
On your grid _prepareColumns()
$this->addColumn('banner_gral', array(
....
'type' => 'checkbox',
'index' => 'banner_gral',
'values' => array(1,2),
'field_name' => 'checkbox_name',
....
));
#R.S answered one issue, how to save the checkbox value on the corresponding model/database field. But the issue on how to correctly display the checkbox on both the grid and the form was not solved. After doing some more searches I finally got to these two links that helped me solve my problem.
To correct the grid issue: Understanding the Grid Serializer Block
Now the part of code where the checkbox column is added, see that I added array(1,2) on the values element.
$this->addColumn('banner_gral', array(
'header' => Mage::helper('banners')->__('General'),
'width' => '20px',
'type' => 'checkbox',
'align' => 'center',
'index' => 'banner_gral',
'values' => array(1,2),
'editable' => 'false',
));
Also if you take a look into the core code of Magento, the class Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Checkbox returns an array of values. Taking a look here finally got me into the right path.
/**
* Returns values of the column
*
* #return array
*/
public function getValues()
{
if (is_null($this->_values)) {
$this->_values = $this->getColumn()->getData('values') ? $this->getColumn()->getData('values') : array();
}
return $this->_values;
}
To correct the form issue: Mage_Adminhtml_Block_System_Store_Edit_Form Class Reference
The issue on this case was that I was trying to use the $this but what I needed to use was the $data that is loaded at the beginning of the _prepareForm function. #R.S pointed the right direction, but it is not possible to use $model->getBannerGral() as the $data on the registry is an array, not a model. So, using $data["banner_gral"] I could get the needed value for the checkbox. Tested and it is working.
$fieldset->addField('banner_gral', 'checkbox', array(
'label' => Mage::helper('banners')->__('Is general'),
'name' => 'banner_gral',
'checked' => $data["banner_gral"],
'onclick' => 'this.value = this.checked ? 1 : 0;',
'note' => Mage::helper('banners')->__('blablablabla'),
'tabindex' => 2
));
Related
I have a form whose content is created from a DB.
in my controller i have:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
//here I get all the data from DB and create the form
if ($form->isValid())
{
//here I do all the relevant changes in the DB
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
It updates the info on the DB properly, but it does not build again the form with updated data. Instead of the return inside the "isValid()" I simply need a refresh on the current page.
I assume it's possible and easy to accomplish, but I failed to find how to do it :/
EDIT - here comes more relevant code:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
$user = $this->container->get('security.context')->getToken()->getUser(); //get current user
$em = $this->getDoctrine()->getManager(); //connect to DB
$prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($projectID);
[...]
// here comes some code to generate the list of $HRsInThisProject and the list of roles ($rolesListForForm)
[...]
foreach ($HRsInThisProject as $key => $HR)
{
$form->add('roleOf_'.$key, 'choice', array('choices' => $rolesListForForm, 'required' => true, 'data' => $HR['role'], 'label' => false, ));
$form->add('isActive_'.$key, 'choice', array('choices' => [0 => 'Inactive', 1 => 'Active'] , 'required' => true, 'data' => $HR['is_active'], 'label' => false, ));
}
[...]
// here there is some code to get the $HRsInMyDomainForForm
[...]
$form->add('HRid', 'choice', array('choices' => $HRsInMyDomainForForm,'required' => false, 'placeholder' => 'Choose a resource', 'label' => false, ));
$form->add('role', 'choice', array('choices' => $rolesListForForm,'required' => false, 'placeholder' => 'Choose a role', 'label' => false, ));
$form->add('save', 'submit', array('label' => 'Save'));
$form->handleRequest($request);
if ($form->isValid())
{
{
[...] here there is a huge portion of code that determines if I need to generate a new "event" to be stored, or even multiple events as I can change several form fields at once
// If I needed to create the event I persist it (this is inside a foreach)
$em->persist($newHREvent);
}
$em->flush();
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
I also include a screenshot of the form:
If a user selects to add a new resouce, I need to persist it to DB (and that is done properly) but then I need to see it in the list of available HRs, without the need for the user to reload the page.
More dynamic way would be:
$request = $this->getRequest();
return $this->redirectToRoute($request->get('_route'), $request->query->all());
or simply
return $this->redirect($request->getUri());
I managed to solve it in a simple (and I hope correct) way.
I simply substituted the "render" inside the isValid() with the following:
return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $prj->getId())));
I works, but does anybody foresee problems with this solution?
You have to link the form to the request.
$entity = new Entity();
$form = $this->createFormBuilder($entity)
->add('field1', 'text')
->add('field2', 'date')
->add('save', 'submit', array('label' => 'Submit'))
->getForm();
$form->handleRequest($request); // <= this links the form to the request.
only after that you test $form->isValid() and pass this form when rendering the template. If you already did this and haven't included in the code above please show more code for better help.
Here is the right way to do it. Event though you have $projectId slug, in Action you can pass whole Object, in this case Project. Symfony will take care for the rest (fetching right Project entity for you.
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, Project $project)
{
$form = $this->createForm(new ProjectType(), $project);
$form->handleRequest($request);
// ... your business logic or what ever
//here I get all the data from DB and create the form
if ($form->isValid() && $form->isSubmitted()) {
$em->persist($project);
// no need to flush since entity already exists
// no need to redirect
}
// here $form->createView() will populate fields with data since you have passed Poroject $project to form
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
Update
According to your edit, you need to use javascript for client-side dom manipulation. Check this link from Symfony official document embedded forms. Here you'll find an example of what you're trying to accomplish.
I m working on prestasshop and I created a helper form inside a controller (for back office). My question is how to upload a document by using the type:'file' from the helper form. Here is the code:
public function __construct()
{
$this->context = Context::getContext();
$this->table = 'games';
$this->className = 'Games';
$this->lang = true;
$this->addRowAction('edit');
$this->addRowAction('delete');
$this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'),
'confirm' => $this->l('Delete selected items?')));
$this->multishop_context = Shop::CONTEXT_ALL;
$this->fieldImageSettings = array(
'name' => 'image',
'dir' => 'games'
);
$this->fields_list = array(
'id_game' => array(
'title' => $this->l('ID'),
'width' => 25
)
);
$this->identifier = 'id_game';
parent::__construct();
}
public function renderForm()
{
if (!($obj = $this->loadObject(true)))
return;
$games_list = Activity::getGamesList();
$this->fields_form = array(
'tinymce' => true,
'legend' => array(
'title' => $this->l('Game'),
'image' => '../img/admin/tab-payment.gif'
),
'input' => array(
array(
'type' => 'select',
'label' => $this->l('Game:'),
'desc' => $this->l('Choose a Game'),
'name' => 'id_games',
'required' => true,
'options' => array(
'query' => $games_list,
'id' => 'id_game',
'name' => 'name'
)
),
array(
'type' => 'text',
'label' => $this->l('Game Title:'),
'name' => 'name',
'size' => 64,
'required' => true,
'lang' => true,
'hint' => $this->l('Invalid characters:').' <>;=#{}'
),
array(
'type' => 'file',
'label' => $this->l('Photo:'),
'name' => 'uploadedfile',
'id' => 'uploadedfile',
'display_image' => false,
'required' => false,
'desc' => $this->l('Upload your document')
)
)
);
$this->fields_form['submit'] = array(
'title' => $this->l(' Save '),
'class' => 'button'
);
return AdminController::renderForm();
}
Now how can I upload the document?
Do I have to create a column in the table of the db (games table) for storing the file or something related?
Thanks in advance
I assume this AdminController for your model. Now a model obviously can't hold a file in table column. What you can do is hold path to the uploaded file. That's what you can save.
You should look in AdminController class (which you extended). When you submit a form, one of two method are executed:
processAdd()
processUpdate()
Now investigate the flow logic in these methods. Other methods are called from within this methods, such as:
$this->beforeAdd($this->object); -> calls $this->_childValidation();
$this->validateRules();
$this->afterUpdate($object);
As you can see, there these are the methods where you can do you custom stuff. If you look up these functions in AdminController class, the're empty. They are purposely added so people can override them and put their custom logic there.
So, using these functions, you can validate your uploaded file fields (even though it isnt in the model itself), if it validates you can then assign path to the object; and then in beforeAdd method you can actually move the uploaded file to the desired location (because both child validation and default validation has passed).
The way I've done it:
protected function _childValidation()
{
// Check upload errors, file type, writing permissions
// Use $this->errors['file'] if there is an error;
protected function beforeAdd($object)
{
// create filename and filepath
// assign these fields to object;
protected function afterAdd($object)
{
// move the file
If you allow the file field to be updated, you'll need to to these steps for Update methods as well.
you can get uploaded file using $_FILES['uploadedfile'] in both the functions processAdd() and processUpdate(), you can check all the conditions there and before calling $this->object->save(); to save the form data you can write the code to upload the file in the desired location like
move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)
since you can't save the file in database you need to save only the name of the file or location on the database
Hope that helps
I have a form in Zend Framework 1. when I click on edit button I want to display values from databases in the form. but I don't know how to do it.
This is my form code:
// Add an email element
$this->addElement('text', 'orgname', array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators'=>Array(
'ViewHelper','Errors'
)
));
This is my controller:
public function editclientcompanyAction()
$form = new Application_Form_Companyform();
$form->addform();
$this->view->form = $form;
$request = $this->getRequest();
$editid=$request->getParam('id');
$edit_show = new Application_Model_Clientcompany;
$showdetails = $edit_show->editclient($editid);
$this->view->assign('datas', $showdetails);
How do I display database vlaues in my Zend Form?
There are two cases.
1) Populating form which has fields same like the database table fields : If you have the form which has same fields like the database fields, then you can populate them easily.
First you need to get the data from the database and then call the Zend_Form populate function passing the data as an associative array, where keys will be same like form fields names and values will be values for the form fields, as below in case of your form.
This will be in your controller
$data = array("orgname" => "Value for the field");
$form = new Application_Form_Companyform();
$form->populate($data);
Now send will automatically populate the form field orgname. You dont need to modify your form or set the value field in the addElement.
*2)Setting field value manually: * The second case is to set the value manually. First you will need to modify your form and add a constructor to it. Also in your form class you will need to create a property (if you have multiple fields, then you can create an array property or multiple properties for each field. This will be all up to you.). And then set the value key in the addElement. Your form should look like this
class Application_Form_Companyform extends Zend_Form
{
private $orgname;
public function __contruct($orgname)
{
$this->orgname = $orgname;
//It is required to call the parent contructor, else the form will not work
parent::__contruct();
}
public function init()
{
$this->addElement('text', 'orgname',
array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators'=>Array('ViewHelper','Errors'),
'value'=>$this->orgname
)
));
} //end of init
} //end of form
Now your controller, you will need to instantiate the form object passing the value of the orgname field like below
$form = new Application_Form_Companyform("This is the value for orgname");
And thats it.
I used such methods and it works like a charm. For your requirements, you may need to adjust the above sample code, as i did not checked it, but it will run fine for sure i hope :P
Thank you
Ok in either ZF1 or ZF2 just do this.
// Add an email element
$this->addElement('text', 'orgname',
array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators' => Array('ViewHelper','Errors'),
'value' => $showdetails->orgname
)
));
You might want to test first for null/empty values first though, you could use ternary operators for convenience:
// Add an email element
$this->addElement('text', 'orgname',
array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators' => Array('ViewHelper','Errors'),
'value' => empty($showdetails->orgname)? null : $showdetails->orgname
)
));
Please have a look in my edit function at /var/www/html/zend1app/application/controllers/CountryController.php :
public function editAction() {
$data = $this->getRequest()->getParams();
$id = (int)$data['id'];
$options = array();
$country = $this->getCountryModel()->fetchRow("id=$id");
if(!$country)
{
throw new Exception("Invalid Request Id!");
}
$form = new Application_Form_Country();
$form->addIdElement();
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())){
$data = new Application_Model_Country();
if($data->save($form->getValues()))
{
$message = array("sucess" => "Country has been updated!");
}
else {
$message = array("danger" => "Country could not be updated!");
}
$this->_helper->FlashMessenger->addMessage($message);
return $this->_helper->redirector('index');
}
}
$options = array (
'id' => $country->id,
'name' => $country->name,
'code' => $country->code
);
$form->populate( $options ); // data binding in the edit form
$this->view->form = $form;
}
and form class at /var/www/html/zend1app/application/forms/Country.php :
class Application_Form_Country extends Zend_Form
{
public function init()
{
// Set the method for the display form to POST
$this->setMethod('post');
// Add an email element
$this->addElement('text', 'name', array(
'label' => 'Enter Country Name:',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
array('validator' => 'StringLength', 'options' => array(0, 20))
)
));
// Add the comment element
$this->addElement('text', 'code', array(
'label' => 'Enter Country Code:',
'required' => true,
'validators' => array(
array('validator' => 'StringLength', 'options' => array(0, 20))
)
));
// Add the submit button
$this->addElement('submit', 'submit', array(
'ignore' => true,
'label' => 'Save',
));
// And finally add some CSRF protection
$this->addElement('hash', 'csrf', array(
'ignore' => true,
));
}
public function addIdElement()
{
$this->addElement('hidden', 'id');
}
}
HTH
I have something like in my custom module:
$fieldset->addField('orderinfo', 'link', array(
'label' => Mage::helper('web')->__('Order Info'),
'style' => "",
'href' => Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('order_id' => $order_id)),
'value' => 'Magento Blog',
'after_element_html' => '',
));
And as you can see from the code, I am trying to link that field to the Order Tab in the back-end. I'm having trouble getting the ID though. I'm planning to just save the Order ID in the database, and then using the addField I could have the correct url.
But how can I save an addField value to a variable?
I want to store the value in "$order_id".
Is it possible?
I am not sure in which context you are using this fieldset but if it is used for example for creating or editing object you can try something like that:
In controller:
public function editAction()
{
$id = $this->getRequest()->getParam('id');
$model = Mage::getModel('module/model')->load($id);
Mage::register('model_name', $model);
}
and then in the block:
protected function _prepareForm()
{
$model = Mage::registry('model_name');
// add fieldset to form
$fieldset->addField('orderinfo', 'link', array(
'label' => Mage::helper('web')->__('Order Info'),
'style' => "",
'href' => Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('order_id' => $model->getOrderId())),
'value' => 'Magento Blog',
'after_element_html' => '',
));
//rest of the elements
}
Answering my own post again. (src: https://magento.stackexchange.com/questions/682/module-forms-store-value-of-addfield-to-a-variable)
I have a tableselect form that lists several items. When a user selects one or more items, and clicks the edit button, I want a new form to show up that lets them edit the items.
I have the new form structure being generated, but I can't get it to show up after the edit button is clicked.
Currently, nothing seems to happen. I know that the tableselect form is being submitted correctly, and the function to create the edit term form is working correctly. I tested it with drupal_set_message and var export.
So, how do I get the new form to show?
Here is my relevant code:
/**
* Generate form for listing terms
*/
function markit_form_terms_list()
{
$form = array();
$form['terms'] = array(
'#type' => 'fieldset',
'#title' => t('List of Terms'),
);
$header = array(t('Name'), t('ID'), t('SetID'));
$form['terms']['items'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#title' => t('Terms'),
'#options' => markit_get_array_terms(),//drupal_map_assoc($header, 'markit_get_array_terms'),
'#tree' => TRUE,
);
$form['terms']['submit'] = array(
'#type' => 'submit',
'#value' => t('Edit Term'),
'#submit' => array('markit_form_terms_list_submit'),
);
/*$form['terms']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete Term'),
'#submit' => 'markit_form_terms_delete'
);*/
return $form;
}
/**
* Generate form to edit the terms.
* #param <type> $form
* #param <type> $form_state
* #return string
*/
function markit_form_term_edit($form, $form_state)
{
$newform = array();
$newform['termstoedit'] = array(
'#type' => 'fieldset',
'#title' => t('Edit Term/s'),
);
foreach($form_state['values']['items'] as $row)
{
if($row!=0)//if a row is not selected, it will be 0. So don't select rows equal to 0.
{
$terminfo = markit_get_markterms($row);
drupal_set_message(var_export($terminfo,true));//['term_name']);
drupal_set_message($terminfo[0]['term_name']);
$newform['termstoedit'][$terminfo[0]['term_id']] = array(
'#type' => 'textfield',
'#title' => t('Term:'),
'#default_value' => $terminfo[0]['term_name'],
'#size' => 60,
'#maxlength' => 128,
'#required' => TRUE,
);
}
}
$newform['termstoedit']['submit'] = array(
'#type' => 'submit',
'#value' => t('Edit Term'),
'#submit' => array('markit_form_term_edit_submit'),
);
drupal_set_message(var_export($newform,true));
return $newform;
}
function markit_form_terms_list_submit($form,$form_state)
{
drupal_set_page_content(drupal_build_form('markit_form_term_edit', $form_state));
}
I believe I am not using the correct code in the markit_form_terms_list_submit function. I've tried several different things, but it hasn't worked yet. And the Google searches I've done haven't helped either. I also have searched the Drupal API and Drupal Form API sites extensively.
Anyway, I think that's all the info you might need in order to help me. Thanks in advance!
I believe you may have better luck if you have one form function with differing fields being shown depending on the output.
If you do this you will even be able to use the form ajax methods to auto update your form.
Have a look at this howto to see if you think the approach will work for you.