I've been googling most of the day trying to find an answer to this, but I've finally admitted defeat.
I'm working on a form in Zend Framework that needs to be able to handle variable data lengths. I have a form with some general fields that specify some general parameters (item name, language, etc) that are easy enough to deal with, but I've also got a subform called parameters which holds a variable number of key/value lairs that let you add generic parameters into the data. Demonstration form follows:
<form>
<input type="text" name="item_name" />
<input type="text" name="item_lang" />
<!-- etc -->
<input type="text" name="parameters[1][key]" />
<input type="text" name="parameters[1][value]" />
<input type="text" name="parameters[2][key]" />
<input type="text" name="parameters[2][value]" />
<input type="text" name="parameters[3][key]" />
<input type="text" name="parameters[3][value]" />
<input type="text" name="parameters[4][key]" />
<input type="text" name="parameters[4][value]" />
<!-- and so on -->
</form>
Note: the above is a massive simplification of the actual form. It's also manually built instead of being generated by zend_form.
The number of parameters can differ and can be handled client side with javascript, but I'm really struggling to initialize a form when populating it from pre-existing data for update.
I might have 2 parameters stored per item, I might have 20, I might have none at all. So I need the form to have 2 or 20 or no parameters inputs depending on the initial state of the data. Unfortunately the data is not available in init () because it's not in the form until you call setDefaults () on it.
This means I can't do a foreach() on the initial state of the form to generate the appropriate number of input boxes for the already-existing data.
I'm sure I must be missing something obvious, but the Zend documentation is pretty dreadful and I can't find any examples of this use case. It surely can't be so uncommon that it's not supported in zend_form. How do I go about generating the form in a state that allows for the initial state of the form to be variable?
ETA: The init() method on my form looks something like this (simplified to match the example):
public function init ()
{
parent::init ();
$this -> addElement ('text', 'item_name');
$this -> addElement ('text', 'item_lang');
$this -> addSubForm (new Zend_Form_SubForm (), 'parameters');
foreach ($phantom_data as $key => $val)
{
$params = new Zend_Form_SubForm ();
$params -> addElement ('text', 'key');
$params -> addElement ('text', 'value');
$this -> parameters -> addSubForm ($params, $key);
}
}
You can make data avaialbe to form like
My_Form extends Zend_Form
{
protected $_myCustomData;
public function __construct($options = null,$myCustomData)
{
$this->_myCustomData = $myCustomData;
parent::__construct($options); //Its important you call parent after above line or init will get call before initilizing customData
}
public function init()
{
$this->_myCustomData ; //here you are free to use your custom data
}
}
Related
I have to set id for Zend Framework form. I have tried this
but it appends some encrypted string at the end of the id.
Following is my code:
public function init()
{
$this->setAttrib('id', 'my_form');
$this->setName('form_test');
$this->setSubmitLabel($this->translate('Save Changes'));
$this->setValidatePartial(true);
}
In Browser it shows as
<input name="instance_name" id="my_form_instance_name-kchovmizxlas" value="" aria-describedby="desc_my_form_instance_name-kchovmizxlas" type="text">
Can I use the id name my_form in my jQuery code or need to change the attribute.
I have a PHP form that need to submit a array of numbers, what we have in view:
<input type="text" id="ProductForm_sizeobj_1" name="ProductForm[sizeobj[1]]" value="13">
<input type="text" id="ProductForm_sizeobj_2" name="ProductForm[sizeobj[2]]" value="13">
<input type="text" id="ProductForm_sizeobj_3" name="ProductForm[sizeobj[3]]" value="13">
And I define in form class:
public $sizeobj = array();
public function rules() {
return array(
array('/** other attributes **/, sizeobj', 'safe')
);
}
Since "Sizeobj" is a dynamic attribute and the size will growth more then 3, therefore I use array. However after form submitted the error throw as follow:
Failed to set unsafe attribute "sizeobj[1" of "ProductForm".
I believe I might using the wrong method to setup array attribute, or wrong rule, any advice? I'm new to Yii, any help is appreciated.
Use name="ProductForm[sizeobj][1]" instead of name="ProductForm[sizeobj[1]]"
The Question: How do I insert values from a database table (#__mytable) into form text fields (motitle and modescription) which have been rendered from an XML file within the Joomla 3.0 platform?
-
I've been trying for days to solve this "easy" Joomla! based undocumented challenge.
I have followed Joomla!'s guide for Developing an MVC, read most of their out-of-date documentation and torn apart the com_content component but have still no idea how to populate my fields.
I've been playing with $this->form->bind($this->item);.
Below I have included some of my code to show the structure I am using. Please feel free to point out any issues you spot along the way.
Models\Forms\item.xml
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="groupOPTIONS">
<fieldset name="Options">
<field
type="text"
name="motitle"
id="motitle"
label="Title"
description="MY TEXT FIELD DESCRIPTION"
maxLength="255" />
<field
type="textarea"
name="modescription"
id="modescription"
label="Description"
description="MY TEXT FIELD DESCRIPTION"
rows="15"
cols="5"
maxLength="255" />
</fieldset>
</fields>
</form>
Models\item.php
jimport('joomla.application.component.modelitem');
class MagicObjectsModelItem extends JModelForm {
public function getForm($data = array(), $loadData = true) {
// Get the form 'items'
$form = $this->loadForm('com_magicobjects.item', 'item',
array('control' => 'jform', 'load_data' => $loadData));
if (empty($form)) {
return false;
}
return $form;
}
protected function loadFormData() {
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_magicobjects.item.edit.data', array());
if (empty($data)) {
$data = $this->getDBItem(1);
}
return $data;
}
public function getDBItem($pk) {
//Obtain JDatabase static connection
$oDb = JFactory::getDbo();
$oQuery = $oDb->getQuery(true);
$sValueToMatch = $pk;
$oQuery
->select(array('mid', 'name', 'keyword', 'description'))
->from('#__mytable')
->where('mid = "' . $sValueToMatch . '"')
->order('mid ASC');
$oDb->setQuery($oQuery);
return $oDb->loadObjectList();
}
views\item\view.html.php
jimport('joomla.application.component.view');
function display($tpl = null) {
// Initialise variables.
$this->form = $this->get('Form');
$this->item = $this->get('Item');
//Display the view
parent::display($tpl);
}
Views\item\tmpl\default.php
foreach ($this->form->getFieldset('Options') as $field) {
echo $field->label;
echo $field->input;
}
By performing a print_r() on item I can see I have the data, but I need to insert the data into the fields shown.
In case this it's still a problem because the form definition is defining a <fields /> group.
This mean that the form fields will be output as follows:
input type="text" name="[groupOPTIONS][motitle]"
based on the example you give above. If you remove the fields grouping it will probably work. It's annoying though as certain JForm methods only work on groups...
You would probably need to change the way in which the data was being passed into the form if you wanted to keep the fields grouping (e.g. by overloading getItem).
Hope that makes sense...
In Joomla 3, the JForm::bind() method appears to accept either an object or associative array as a parameter. All of the object/array fields are then stored in a protected JRegistry type data member called JForm::$data.
When you're trying to display a form field (by calling JForm::getInput()), the call stack is as follows
JForm::getInput() -> JForm::getField() -> JForm::loadField() -> JForm::getValue()
JForm::getValue() returns a value from the (aforementioned JRegistry) JForm::$data data member. The JForm::loadField() method also passes the default value (defined by the form) to the JForm::getValue() method in case a value in the JForm::$data variable doesn't exist.
In terms of doing this inside a model, you might want to generate a object or assoc array from a database query or table (ensuring that the field names correspond with the field names defined in the form xml) and then pass it to JForm::bind() as a parameter. However, if you are using JModelForm, I think you should only override JModelForm::loadFormData() to pass the object/assoc array to the loaded form.
See : libraries/joomla/form/form.php
Hope that helps :)
Instead of $oDb->loadObjectList(); use $oDb->loadAssoc(); in your getDBItem() function.
Check this - http://docs.joomla.org/Accessing_the_database_using_JDatabase/1.5
Check this also - joomla loadformdata
Hope this will work.
I have a problem with zend form, where i need to built a form where field name are same but with different belongings. Here is the input fields that i wanted inside my form.
Currently i am getting with straight html but because of this i am missing validation.
<input type="text" name="travel_guide_tab[4][title]">
<input type="text" name="travel_guide_tab[4][description]">
<input type="text" name="travel_guide_tab[6][title]">
<input type="text" name="travel_guide_tab[6][description]">
In Zend Form the element names must be unique (in some way) or else they will overwrite. However you can continue using your html form and simply filter and validate in the controller using Zend_Filter_Input. The filter and validation classes are the same ones used by Zend_Form you just pass the data in a different way.
Simple example, partial:
public function someAction() {
//set filters and validators for Zend_Filter_Input
$filters = array(
'nameOfInput' => array('HtmlEntities', 'StripTags')
);
$validators = array(
'nameOfInput' => array('NotEmpty', 'Int')
);
//assign Input
$input = new Zend_Filter_Input($filters, $validators);//can also pass the data in constructor (optional)
$input->setData($this->getRequest()->getParams());
//check input is valid and is specifically posted as 'Delete Selected'
if ($input->isValid()) {
//do some stuff
}
Good Luck.
Making a simple component. If I save a new record with the box checked, it saves fine. If I go back and uncheck a previously checked item it reverts back to checked. I thought it had something to do with a hidden field, played with putting one of those in manually but that didn't fix it either so took it out.
Here's where I'm at:
An xml snippet:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="1"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="1"
filter="intval"
/>
...
</fieldset>
The edit.php file:
<div class="width-45 fltlft">
<fieldset class="adminform">
<legend>Checkboxes</legend>
<ul class="adminformlist">
<?php foreach ($this->form->getFieldset('checks') as $field): ?>
<li>
<?php echo $field->label; ?>
<?php echo $field->input; ?>
</li>
<?php endforeach ?>
</ul>
</fieldset>
</div>
Also added this towards the end before the form.token:
<input type="hidden" name="task" id="task" value="completion.edit" />
I tried deleting the value="1" in the xml but then I had the opposite problem where the check wouldn't save at all.
Any ideas?
Thanks!
=============================
Edit:
Model:
<?php
defined( '_JEXEC' ) or die;
jimport('joomla.application.component.modeladmin');
class AssessModelCompletion extends JModelAdmin
{
//tells it what kind of record and the prefix
public function getTable($type = 'Completion', $prefix = 'AssessTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
//Load the data into the edit form
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_assess.edit.completion.data', array()); //first try to get the data from the session, not db
if (empty($data)) {
$data = $this->getItem(); //this gets the data
}
return $data;
}
//Stores data in a session in case a field is missed
public function getForm($data = array(), $loadData = true)
{
$form = $this->loadForm('com_assess.completion', 'completion', array('control' => 'jform', 'load_data' => $loadData));
return $form;
}
}
And table:
<?php
defined ( '_JEXEC' ) or die;
class AssessTableCompletion extends JTable
{
public function __construct(&$db)
{
parent::__construct('#__tablename_completions', 'completion_id', $db);
}
}
======================================
References:
https://stackoverflow.com/questions/6964333/joomla-1-6-admin-form-processing-grouped-checkboxes-in-form
Tutorial code is not working any more in Joomla 2.5
http://docs.joomla.org/Developing_a_Model-View-Controller_%28MVC%29_Component_for_Joomla!1.7_-_Part_09#Adding_a_toolbar
So this is a kind of odd situation in that the documentation you list makes it seem that you would have to write no code to handle the checkbox (because as you point out a checkbox is different then checkboxes). But this does not seem to be the case because of the way that html checkboxes are submitted.
A quick overview of this issue and one solution can be found here: http://planetozh.com/blog/2008/09/posting-unchecked-checkboxes-in-html-forms/.
To use this, you would need to get the field's name out of the $field variable (which I'm not sure if it will be easy to access) and then place the <input type=hidden name='name' value=0> before <?php echo $field->input; ?>.
The other method to fix this would be to process the form data during save and override elements. Joomla has a prepareTable function that you could add to your model to edit data as necessary during save. The following example assumes that your form elements are wrapped in a jform array. (Confirm this by looking at the name fields in the html generated and they should be 'jform[checkbox1]')
protected function prepareTable(&$table)
{
$jform = JRequest::getVar('jform'); // load all submitted data
if (!isset($jform['checkbox1'])) { // see if the checkbox has been submitted
$table->checkbox1 = 0; // if it has not been submitted, mark the field unchecked
}
if (!isset($jform['checkbox2'])) { // likewise for other checkboxes
$table->checkbox2 = 0;
}
}
In this case, you would want to keep "value=1" in your xml fields file.
The problem ultimately is that Joomla loads the current data from the database during saving and then binds the posted data over the top of it. Because an unchecked box is not submitted in the post data, it does not overwrite the databases information and is thus not saved.
Although the documentation states that you do not have to do any manual handeling of the checkbox this is not true.
As no value is sent in the $_POST array when a checkbox is not checked the value is not overwritten and thus not saved which makes it impossible to uncheck the checkbox. To fix this you have to write special handling for your checkboxes in your table bind() function like this:
class YourcomponentTableYourview extends JTable
{
/**
* Constructor
*
* #param JDatabase A database connector object
*/
public function __construct(&$db)
{
parent::__construct('#__your_table_name', 'id', $db);
}
public function bind($array, $ignore = '')
{
if (!isset($array['name_of_field']))
$array['name_of_field'] = 0 ;
return parent::bind($array, $ignore);
}
}
As you don't have any model/table code showing, I think you may be mistaking JForm's purpose - it is purely for rendering of the form. You still have to have in your model/table something to handle the array that is returned for multivalued fields.
As Sam Moffat put it:
there is no coupling between the form definitions used to render the data and the models and table structures used to persist them
So I had a lot of fields and wanted to simply loop through them in my edit.php field to keep it clean. While all the answers offered were right they weren't easy to implement - got really messy really quickly, had trouble getting it to work, or couldn't figure out a cleaner way around it. I chewed on this for awhile and then today came across what is basically a field override.
The key:
The standard form field types are located in
joomla/libraries/joomla/form/fields/. You should not store custom
fields there, nor should you have to use this path in your own code,
but the standard types are usually good examples.
The custom field types that belong to your component are usually
located in administrator/components//models/fields. You can specify this or another path in your
code
So, I copied checkbox.php to models/fields. Then, towards the end of the file I added the empty field before the checkbox tag:
<input type="hidden" name="'.$this->name.'" id="'.$this->id.'" value="0" /><input type="checkbox" .....
Now, whenever I need a checkbox the empty field is also written. May not be the most efficient solution but simple to implement and can hopefully help someone else.
[Edit]
As a note, with every Joomla update you would probably need to compare the versions in the core in case there was a change.
I know this is an old question, but the official answer is long winded and I think I have a better solution.
Try setting the default value for the checkbox to 0 rather than 1 in your xml like so:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="0"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="0"
filter="intval"
/>
...
</fieldset>
I just came across your question and tried setting it to 0 as I didn't want to tamper with the core and hey presto it works.
My guess is that Joomla sees no value and thus sets the default instead.