When defining your field in your system.xml
file you can specify the source_model
of this field. For example the source model for the standard yes no drop down is as follows.
<source_model>adminhtml/system_config_source_yesno</source_model>
This will tell the field to use the model Mage_Adminhtml_Model_System_Config_Source_Yesno
for building the options. Inside this model you will see the function toOptionArray
which
class Mage_Adminhtml_Model_System_Config_Source_Yesno
{
/**
* Options getter
*
* @return array
*/
public function toOptionArray()
{
return array(
array('value' => 1, 'label'=>Mage::helper('adminhtml')->__('Yes')),
array('value' => 0, 'label'=>Mage::helper('adminhtml')->__('No')),
);
}
}
So using this as a basis for your requirements what you can do is set-up your own model for example Your_Module_Model_System_Config_Region
, then you would simply need to use your table's collection to build the correct structure in the function toOptionArray
.
As far as loading one source model based on the value of another you have two options.
Using Frontend Models
Perfect example of this is the tax options for country and region under app/code/core/Mage/Tax/etc/system.xml
.
Basically what you need to do is create a frontend_model that extends Mage_Adminhtml_Block_System_Config_Form_Field
. This block will only need to have the function _getElementHtml
. What you can do then is call the parent function so the default select is created and show and then add some javascript that will update this select based on when another element has changed.
In the tax example it uses the standard RegionUpdater
but it is possible to work with the more generic SelectUpdater
which allows for one select element to change another.
Now I will show you in depth how this can be achieved. In this example I am using the magento standard country and region collections but you can easily plug in your own collections when needed.
Firstly you will need the system.xml, this should add the correct frontend_model
and source_model
references:
<config>
<tabs>
<example>
<label>Example</label>
</example>
</tabs>
<sections>
<example translate="label" module="example_frontendmodel">
<class>separator-top</class>
<label>Example</label>
<tab>example</tab>
<sort_order>100</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<groups>
<frontend_model translate="label">
<label>Frontend Model</label>
<sort_order>30</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<fields>
<country translate="label">
<label>Default Country</label>
<frontend_type>select</frontend_type>
<source_model>example_frontendmodel/system_config_source_country</source_model>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</country>
<region translate="label">
<label>Default State</label>
<frontend_type>select</frontend_type>
<frontend_model>example_frontendmodel/adminhtml_frontend_region_updater</frontend_model>
<source_model>example_frontendmodel/system_config_source_region</source_model>
<sort_order>20</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</region>
</fields>
</frontend_model>
</groups>
</example>
</sections>
</config>
For this example the two source_models are the same as the standard Mage_Tax
source models so there is nothing special there. But you could here load all the options you need for from your tables.
The next thing of importance is the frontend_model
here what you do is extend the class Mage_Adminhtml_Block_System_Config_Form_Field
and create your own _getElementHtml
function. This function will call the parent _getElementHtml
and set a variable with the returned html. Then you can build your javascript using the SelectUpdater
you can see from the init, in file js/mage/adminhtml/form.js
, that you need to specify the following.
- The first select element's id,
- The second select element's id,
- A default message for use on the second select when the first one is not selected,
- A message to use if the selection from the first select element does not have a match in the second,
- The values for the second element json encoded,
- The current selected item,
My example looks as follows.
<?php
class Example_FrontendModel_Block_Adminhtml_Frontend_Region_Updater
extends Mage_Adminhtml_Block_System_Config_Form_Field
{
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$html = parent::_getElementHtml($element);
$js = '<script type="text/javascript">
var updater = new SelectUpdater(
"example_frontend_model_country",
"example_frontend_model_region",
"none",
"none",
%s,
false
);
updater.update();
</script>';
$html .= sprintf($js, $this->helper('example_frontendmodel')->getRegionJson());
return $html;
}
}
The values are built from my helper and replaced into the html string just before being returned. The easiest way to build the values is to create an array of the following format.
array(
'first_select_value1' => array(
'second_select_value1' => 'second_select_text1',
'second_select_value2' => 'second_select_text2',
),
'first_select_value2' => array(
'second_select_value3' => 'second_select_text3',
'second_select_value4' => 'second_select_text4',
)
)
Here is my example's helper for building the values, but you could easily extend it to use what ever collections you need for your need.
<?php
class Example_FrontendModel_Helper_Data extends Mage_Core_Helper_Abstract {
public function getRegionJson()
{
/**
* array(
* 'first_value' => array(
* 'second_value' => 'second_txt'
* )
* )
*/
$countryIds = array();
$countryCollection = Mage::getModel('directory/country')->getResourceCollection()
->loadByStore();
foreach ($countryCollection as $country) {
$countryIds[] = $country->getCountryId();
}
$collection = Mage::getModel('directory/region')->getResourceCollection()
->addCountryFilter($countryIds)
->load();
$regions = array();
foreach ($collection as $region) {
if (!$region->getRegionId()) {
continue;
}
$regions[$region->getCountryId()][$region->getRegionId()] = $this->__($region->getName());
}
return Mage::helper('core')->jsonEncode($regions);
}
}
The adminhtml_sales_order_create_process_data
event also contains the order creation model, which you can access like this:
/** @var Mage_Adminhtml_Model_Sales_Order_Create $model */
$model = $observer->getEvent()->getOrderCreateModel();
From there you should be able to modify the quote to suit your needs.
If you're looking to modify the shipping form template (or it's data), then you'll need to add/modify blocks and/or templates instead of using an event observer.
The adminhtml_sales_order_create_load_block_shipping_method
layout handle is added whenever Magento needs to display the shipping method form. This handle is used to load two blocks:
<adminhtml_sales_order_create_load_block_shipping_method>
<reference name="content">
<block type="adminhtml/sales_order_create_shipping_method" template="sales/order/create/abstract.phtml" name="shipping_method">
<block type="adminhtml/sales_order_create_shipping_method_form" template="sales/order/create/shipping/method/form.phtml" name="form" />
</block>
</reference>
</adminhtml_sales_order_create_load_block_shipping_method>
If you're familiar with layouts, you should have no problem making whatever changes you need to. For example, if you wanted to override the form block, you could create your own adminhtml layout file with the following contents:
<?xml version="1.0"?>
<layout>
<adminhtml_sales_order_create_load_block_shipping_method>
<reference name="shipping_method">
<remove name="form" />
<block type="yourmodule/overrides_sales_order_create_shipping_method_form" template="yourmodule/sales/order/create/shipping/method/form.phtml" name="form" />
</reference>
</adminhtml_sales_order_create_load_block_shipping_method>
</layout>
Hope that helps!
Best Answer
Remembering we are following this tutorial: http://markshust.com/2012/07/05/creating-magento-adminhtml-grids-simplified
The short answer is...
Create the function below to serve as source to dropdown in the page
app\code\community\Foo\Bar\Block\Adminhtml\Baz\Edit\Form.php
... and add it to 'values' parameter in the 'select' field:
And the long answer is...
1) Add the new entity chuz to
app\code\community\Foo\Bar\etc\config.xml
2) In the file
app\code\community\Foo\Bar\sql\foo_bar_setup\mysql4-install-1.0.0.php
do the following...Add the new column
chuz
to the tablefoo_bar_baz
And make the script for creating new table
foo_bar_chuz
3) Create the Model files, as follows...
4) Finally do the steps from the
Short Answer
part.5) Do not forget to insert some rows to
foo_bar_chuz
manually, because we do not have create form for it!The result should be as follows: