I want to show filter of category on submenu, my code works!!
My problem is that if page are already filtered, my code does not return the options
I believe it has to do something in the code that bypasses the filter page and again bring the options in the submenu even if already have the filter on page
HTML of submenu:
{{block type="core/template" category="3" template="page/html/icons_submenu.phtml"}}
Content of page icons_submenu.phtml:
<?php
$layer = Mage::getModel("catalog/layer");
$category = Mage::getModel('catalog/category')->load($this->getCategory());
$layer->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getAttributeCode() == 'color') {
$filterBlockName = 'catalog/layer_filter_attribute';
$result = Mage::app()->getLayout()->createBlock($filterBlockName)->setLayer($layer)->setAttributeModel($attribute)->init();
echo '<strong>Color:</strong><br />';
foreach($result->getItems() as $option) {
echo ' ' . $option->getValue() . ' - ' . $option->getLabel() . '<br />';
}
}
}
?>
Example:
I would really suggest you to actually move all that logic into a proper module, a proper block and a proper model and not in a template like you are doing right now.
If you actually want further help for that, feel free to ask, making something according to the coding guide lines of Magento would make you even happier of your job, I can assure you.
This being said, what you actually want is a current filter model based on the current category and a specify attribute.
You don't need to go by the block catalog/layer_filter_attribute in a way to do this, you can directly go by the model based on the layer you already load.
So, this way of doing it should work, although it should not be in a template or view, once again :
<?php
$category = Mage::getModel('catalog/category')
->load($this->getCategory());
$layer = Mage::getModel('catalog/layer')
->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getAttributeCode() == 'color') {
// $filterBlockName = 'catalog/layer_filter_attribute';
/** This is actually your only problem in your code **/
// $result = Mage::app()->getLayout()->createBlock($filterBlockName)->setLayer($layer)->setAttributeModel($attribute)->init();
/** But would work with this line **/
$result = Mage::getModel('catalog/layer_filter_attribute')
->setLayer($layer)
->setAttributeModel($attribute);
echo '<strong>Color:</strong><br />';
foreach($result->getItems() as $option) {
echo ' ' . $option->getValue() . ' - ' . $option->getLabel() . '<br />';
}
}
}
?>
Then you can see it still works based on only the colours I have in the current category
But also when the category is already filtered on a specific colour
How can i display uploaded file name or link after successfully uploaded file at magento custom module form.I had attached screenshot for clear understanding.Please help
In order to do this, you need a custom renderer for the file input in your form.
For this create the following class:
<?php
class {{Namespace}}_{{Module}}_Block_Adminhtml_{{Entity}}_Helper_File extends Varien_Data_Form_Element_Abstract{
public function __construct($data){
parent::__construct($data);
$this->setType('file');
}
public function getElementHtml(){
$html = '';
$this->addClass('input-file');
$html.= parent::getElementHtml();
if ($this->getValue()) {
$url = $this->_getUrl();
if( !preg_match("/^http\:\/\/|https\:\/\//", $url) ) {
$url = Mage::getBaseUrl('media').'{{entity}}'.'/'.'file' . $url; //replace this with the path to the file if you upload it somewhere else
}
$html .= '<br />'.$this->_getUrl().' ';
}
$html.= $this->_getDeleteCheckbox();
return $html;
}
protected function _getDeleteCheckbox(){
$html = '';
if ($this->getValue()) {
$label = Mage::helper('{{module}}')->__('Delete File');
$html .= '<span class="delete-image">';
$html .= '<input type="checkbox" name="'.parent::getName().'[delete]" value="1" class="checkbox" id="'.$this->getHtmlId().'_delete"'.($this->getDisabled() ? ' disabled="disabled"': '').'/>';
$html .= '<label for="'.$this->getHtmlId().'_delete"'.($this->getDisabled() ? ' class="disabled"' : '').'> '.$label.'</label>';
$html .= $this->_getHiddenInput();
$html .= '</span>';
}
return $html;
}
protected function _getHiddenInput(){
return '<input type="hidden" name="'.parent::getName().'[value]" value="'.$this->getValue().'" />';
}
protected function _getUrl(){
return $this->getValue();
}
public function getName(){
return $this->getData('name');
}
}
Then you need to tell your for to use this for the file inputs. So in your edit form tab, add this right after defining the fiedlset:
$fieldset->addType('file', Mage::getConfig()->getBlockClassName('{{module}}/adminhtml_{{entity}}_helper_file'));
Replace {{Namespace}}, {{Module}} and {{Entity}} with the appropriate values keeping the case.
Namespace is the namespace of your module (D'uh), Module is the name of your module (D'uh again), and Entity is what you are managing. Can be Article, News, Files....
[EDIT]
You can build your module using this module creator. It takes care of these kind of issues.
Note: I hope this is not considered self promotion. The extension is free and I get no financial benefits out of it.
Ok I found answer myself...
just create one file and extended it with magento core abstract class that is Namespace_ModuleName_Block_Adminhtml_Modulename_Helper_File extends Varien_Data_Form_Element_Abstract
and added below code to admin form
$fieldset = $form->addFieldset('Module_form', array('legend'=>Mage::helper('Module')->__('Video information')));
$fieldset->addType('file', Mage::getConfig()->getBlockClassName('Module/adminhtml_Module_helper_file')); /* line added */
I have been using this documentation (the only one I can find on the web) to build a component:
http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Introduction
I can understand it to a certain extent, however it does really lack any definition. The component I have created works to a degree, though I am having some wier problems.
Basically all I need the component to do is simply load a settings area to set a few values, and through it be able to change those values. Here is a breakdown of what I have:
A view for a form, loading in form data from database.
toolbars setup for save/apply and cancel.
This loads with no errors, and according to all docs on joomla I have found, by initializing a JControllerForm instance with a JTable connected in the model, simple saving of forms should work automatically. However even though there is absolutely no reference anywhere in the code to a view with an s at the end (main view is tireapi, the forms always redirects to tireapis).
This brings up a 500 error, as there is no place set that has that view. The documentation does include a list for a view, however I have only one row I need to edit, so a list is pointless. I know parameters can be set to components rather then making a database field, however I am unable to find any documentation relating to it.
What I am looking for is direction on how to stop the component from redirecting to a none existent view, and properly save the data. Links to documentation that not only shows example code, but describes functions and how they work would be beneficial.
Here is some of the code, feel free to point out anything I might be completely overlooking (I am newer to creating components):
tireapi.php:
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import joomla controller library
jimport('joomla.application.component.controller');
// Get an instance of the controller prefixed by TireAPI
$controller = JController::getInstance('TireAPI');
// Get the task
$jinput = JFactory::getApplication()->input;
$task = $jinput->get('task', "", 'STR' );
// Perform the Request task
$controller->execute($task);
// Redirect if set by the controller
$controller->redirect();
?>
controller.php:
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla controller library
jimport('joomla.application.component.controller');
class TireAPIController extends JController{
function display($cachable = false){
// set default view if not set
$input = JFactory::getApplication()->input;
$input->set('view', $input->getCmd('view', 'TireAPI'));
// call parent behavior
parent::display($cachable);
}
}
?>
controllers/tireapi.php:
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla controllerform library
jimport('joomla.application.component.controllerform');
class TireAPIControllerTireAPI extends JControllerForm{}
?>
models/tireapi.php:
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import the Joomla modellist library
jimport('joomla.application.component.modeladmin');
class TireAPIModelTireAPI extends JModelAdmin{
protected $settings; //define settings
public function getTable($type = 'TireAPI', $prefix = 'TireAPITable', $config = array()){
return JTable::getInstance($type, $prefix, $config);
}
public function getSettings(){ //grab settings from database
if(!isset($this->settings)){
$table = $this->getTable();
$table->load(1);
$this->settings = $table;
}
return $this->settings;
}
public function getForm($data = array(), $loadData = true){
// Get the form.
$form = $this->loadForm('com_tireapi.tireapi', 'tireapi',
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_tireapi.edit.tireapi.data', array());
if (empty($data)){
$data = $this->getSettings();
}
return $data;
}
}
?>
tables/tireapi.php:
<?php
// No direct access
defined('_JEXEC') or die('Restricted access');
// import Joomla table library
jimport('joomla.database.table');
class TireAPITableTireAPI extends JTable
{
function __construct( &$db ) {
parent::__construct('#__tireapi', 'id', $db);
}
}
?>
views/tireapi/view.html.php:
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla view library
jimport('joomla.application.component.view');
class TireAPIViewTireAPI extends JView{
function display($tpl = null){
$form = $this->get('Form');
$item = $this->get('Settings');
// Check for errors.
if(count($errors = $this->get('Errors'))){
JError::raiseError(500, implode('<br />', $errors));
return false;
}
// Assign data to the view
$this->item = $item;
$this->form = $form;
$this->addToolBar();
// Display the template
parent::display($tpl);
}
protected function addToolBar() {
$input = JFactory::getApplication()->input;
JToolBarHelper::title(JText::_('COM_TIREAPI_MANAGER_TIREAPIS'));
JToolBarHelper::apply('tireapi.apply');
JToolBarHelper::save('tireapi.save');
JToolBarHelper::cancel('tireapi.cancel');
}
}
?>
views/tireapi/tmpl/default.php:
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted Access');
// load tooltip behavior
JHtml::_('behavior.tooltip');
?>
<form action="<?php echo JRoute::_('index.php?option=com_tireapi&layout=edit&id='.(int) $this->item->id); ?>"
method="post" name="adminForm" id="tireapi-form">
<fieldset class="adminform">
<legend><?php echo JText::_( 'COM_TIREAPI_DETAILS' ); ?></legend>
<ul class="adminformlist">
<?php foreach($this->form->getFieldset() as $field): ?>
<li><?php echo $field->label;echo $field->input;?></li>
<?php endforeach; ?>
</ul>
</fieldset>
<div>
<input type="hidden" name="task" value="tireapi.edit" />
<?php echo JHtml::_('form.token'); ?>
</div>
</form>
These are all the files I can think of that may matter, let me know if I should include anymore.
UPDATE:
Now I can get the redirect problem to stop, however it will not save data.
I get this error:
You are not permitted to use that link to directly access that page (#1).
This is the last hurdle to get this extremely basic admin feature to work. Any ideas?
To clarify, I set the forms though an xml file and that loads properly, even filling them with the proper data from database. However when I click "apply" it just directs me back to the form with the error listed above, without saving.
The main question that you left open is where do you want it to redirect? Joomla by default redirects to the list view (by adding an 's' to the view name unless you specify a list view directly).
You can override this in a couple of ways:
In your controller (controllers/tireapi.php), set your own list view. I think you can even make this the same view:
function __construct() {
$this->view_list = 'tireapi';
parent::__construct();
}
Override the save function to change the redirect that happens after save (again in the controller). This works by changing the redirect that happens naturally to something else:
public function save($key = null, $urlVar = null) {
$return = parent::save($key, $urlVar);
$this->setRedirect(JRoute::_('index.php?option=com_tireapi&view=tireapi'));
return $return;
}
One of those should do the trick for you.
** UPDATE
To get the item to checkout initially you will want to change how your component handles no view being set. Right now you just set the view, instead, let's redirect! Updated controller.php is below.
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla controller library
jimport('joomla.application.component.controller');
class TireAPIController extends JController{
function display($cachable = false){
// set default view if not set
$input = JFactory::getApplication()->input;
$view = $input->get('view');
if (!$view) {
JFactory::getApplication()->redirect('index.php?option=com_tireapi&task=tireapi.edit&id=1');
exit();
}
// call parent behavior
parent::display($cachable);
}
}
?>
NOTE: This will work really poorly if more than one person needs to edit this, since the system checks it out when you open the component if you also have it redirect back to this page after saving. Because then it will always be checked out to the last person that edited it so the next person won't be able to open it. If only one person edits it, it will be fine.
SECOND NOTE: If you don't want to hack the checkout system you can also ignore it during the save process, which is basically the same level of hacking.
Below is a copy of the save function from controllerform.php in libraries/joomla/application/component/. This is what is running on save normally (because of where you inherit from. I have removed the check if the item is checked out. So if you put this in your tireapi.php controller where the parent::save... bit is, it will run instead and you don't have to bother with checking the item out (i.e. ignore all the comments...). (Honestly, in your case, you can probably delete a lot more of this, but this is what is happening on save, btw!)
public function save($key = null, $urlVar = null)
{
// Check for request forgeries.
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
// Initialise variables.
$app = JFactory::getApplication();
$lang = JFactory::getLanguage();
$model = $this->getModel();
$table = $model->getTable();
$data = JRequest::getVar('jform', array(), 'post', 'array');
$checkin = property_exists($table, 'checked_out');
$context = "$this->option.edit.$this->context";
$task = $this->getTask();
// Determine the name of the primary key for the data.
if (empty($key))
{
$key = $table->getKeyName();
}
// To avoid data collisions the urlVar may be different from the primary key.
if (empty($urlVar))
{
$urlVar = $key;
}
$recordId = JRequest::getInt($urlVar);
// Populate the row id from the session.
$data[$key] = $recordId;
// The save2copy task needs to be handled slightly differently.
if ($task == 'save2copy')
{
// Check-in the original row.
if ($checkin && $model->checkin($data[$key]) === false)
{
// Check-in failed. Go back to the item and display a notice.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_item
. $this->getRedirectToItemAppend($recordId, $urlVar), false
)
);
return false;
}
// Reset the ID and then treat the request as for Apply.
$data[$key] = 0;
$task = 'apply';
}
// Access check.
if (!$this->allowSave($data, $key))
{
$this->setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
$this->setMessage($this->getError(), 'error');
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_list
. $this->getRedirectToListAppend(), false
)
);
return false;
}
// Validate the posted data.
// Sometimes the form needs some posted data, such as for plugins and modules.
$form = $model->getForm($data, false);
if (!$form)
{
$app->enqueueMessage($model->getError(), 'error');
return false;
}
// Test whether the data is valid.
$validData = $model->validate($form, $data);
// Check for validation errors.
if ($validData === false)
{
// Get the validation messages.
$errors = $model->getErrors();
// Push up to three validation messages out to the user.
for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
{
if ($errors[$i] instanceof Exception)
{
$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
}
else
{
$app->enqueueMessage($errors[$i], 'warning');
}
}
// Save the data in the session.
$app->setUserState($context . '.data', $data);
// Redirect back to the edit screen.
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_item
. $this->getRedirectToItemAppend($recordId, $urlVar), false
)
);
return false;
}
// Attempt to save the data.
if (!$model->save($validData))
{
// Save the data in the session.
$app->setUserState($context . '.data', $validData);
// Redirect back to the edit screen.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_item
. $this->getRedirectToItemAppend($recordId, $urlVar), false
)
);
return false;
}
// Save succeeded, so check-in the record.
if ($checkin && $model->checkin($validData[$key]) === false)
{
// Save the data in the session.
$app->setUserState($context . '.data', $validData);
// Check-in failed, so go back to the record and display a notice.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_item
. $this->getRedirectToItemAppend($recordId, $urlVar), false
)
);
return false;
}
$this->setMessage(
JText::_(
($lang->hasKey($this->text_prefix . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS')
? $this->text_prefix
: 'JLIB_APPLICATION') . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS'
)
);
// Redirect the user and adjust session state based on the chosen task.
switch ($task)
{
case 'apply':
// Set the record data in the session.
$recordId = $model->getState($this->context . '.id');
$this->holdEditId($context, $recordId);
$app->setUserState($context . '.data', null);
$model->checkout($recordId);
// Redirect back to the edit screen.
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_item
. $this->getRedirectToItemAppend($recordId, $urlVar), false
)
);
break;
case 'save2new':
// Clear the record id and data from the session.
$this->releaseEditId($context, $recordId);
$app->setUserState($context . '.data', null);
// Redirect back to the edit screen.
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_item
. $this->getRedirectToItemAppend(null, $urlVar), false
)
);
break;
default:
// Clear the record id and data from the session.
$this->releaseEditId($context, $recordId);
$app->setUserState($context . '.data', null);
// Redirect to the list screen.
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_list
. $this->getRedirectToListAppend(), false
)
);
break;
}
// Invoke the postSave method to allow for the child class to access the model.
$this->postSaveHook($model, $validData);
return true;
}
This is not a real answer but your question is also not a real question (I had to read it 3 times).
The thing with the plural "s" (for tireapis) is what Joomla! does automatically. You can override that.
I suggest that you take a look at the core components (like com_banners).
What you need to do is to avoid the redirect. You should have only the "Save" button, that should keep you on the same page. While "Save & Close" redirects you to the plural page.
How can i use flash messenger in zend freamwork 2? Session documentation is not yet. Anyone know it? But session libraries are there.
Update :
Zend Framework new release added FlashMessenger View Helper , found in path /library/Zend/View/Helper/FlashMessenger.php
FlashMessenger.php
Old answer :
I have written a custom view helper, for printing flash messages
In /module/Application/Module.php
public function getViewHelperConfig()
{
return array(
'factories' => array(
'flashMessage' => function($sm) {
$flashmessenger = $sm->getServiceLocator()
->get('ControllerPluginManager')
->get('flashmessenger');
$message = new \My\View\Helper\FlashMessages( ) ;
$message->setFlashMessenger( $flashmessenger );
return $message ;
}
),
);
}
Create a custom view helper in /library/My/View/Helper/FlashMessages.php
namespace My\View\Helper;
use Zend\View\Helper\AbstractHelper;
class FlashMessages extends AbstractHelper
{
protected $flashMessenger;
public function setFlashMessenger( $flashMessenger )
{
$this->flashMessenger = $flashMessenger ;
}
public function __invoke( )
{
$namespaces = array(
'error' ,'success',
'info','warning'
);
// messages as string
$messageString = '';
foreach ( $namespaces as $ns ) {
$this->flashMessenger->setNamespace( $ns );
$messages = array_merge(
$this->flashMessenger->getMessages(),
$this->flashMessenger->getCurrentMessages()
);
if ( ! $messages ) continue;
$messageString .= "<div class='$ns'>"
. implode( '<br />', $messages )
.'</div>';
}
return $messageString ;
}
}
then simple call from layout.phtml , or your view.phtml
echo $this->flashMessage();
Let me show example of controller action
public function testFlashAction()
{
//set flash message
$this->flashMessenger()->setNamespace('warning')
->addMessage('Mail sending failed!');
//set flash message
$this->flashMessenger()->setNamespace('success')
->addMessage('Data added successfully');
// redirect to home page
return $this->redirect()->toUrl('/');
}
In home page, it prints
<div class="success">Data added successfully</div>
<div class="warning">Mail sending failed!</div>
Hope this will helps !
i have written a post about this some time ago. You can find it right here
Basically you use it just the same like earlier.
<?php
public function commentAction()
{
// ... display Form
// ... validate the Form
if ($form->isValid()) {
// try-catch passing data to database
$this->flashMessenger()->addMessage('Thank you for your comment!');
return $this->redirect()->toRoute('blog-details'); //id, blabla
}
}
public function detailsAction()
{
// Grab the Blog with given ID
// Grab all Comments for this blog
// Assign the view Variables
return array(
'blog' => $blog,
'comments' => $comments,
'flashMessages' => $this->flashMessenger()->getMessages()
);
}
Then in your .phtml file you do it like this:
// details.phtml
<?php if(count($flashMessages)) : ?>
<ul>
<?php foreach ($flashMessages as $msg) : ?>
<li><?php echo $msg; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Obviously this isn't all too handy, as you have to do this for every single .phtml file. Therefore doing it within the layout you have to do it at best like the following:
<?php
// layout.phtml
// First get the viewmodel and all its children (ie the actions viewmodel)
$children = $this->viewModel()
->getCurrent()
->getChildren();
$ourView = $children[0];
if (isset($ourView->flashMessages) && count($ourView->flashMessages)) : ?>
<ul class="flashMessages">
<?php foreach ($ourView->flashMessages as $fMessage) : ?>
<li><?php echo $fMessage; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
If you need further description, please see my blog, but i guess the code itself is pretty clear (apart frmo the layout.phtml example). Alternatively you're always free to write your own view helper to have it look a little cleaner inside your view-templates.
How to grab Flashmessenger’s messages in a View Helper – sharing code as requested by Sam.
The View helper should implement the ServiceManagerAwareInterface interface and related methods. The plugin will now have access to a Service Manager which we can use to get the Service Locator and ultimately access to the Flash Messenger.
I’ve not touched this code since I initially wrote it – so there may be a more elegant way of doing this.
protected function getMessages()
{
$serviceLocator = $this->getServiceManager()->getServiceLocator();
$plugin = $serviceLocator->get('ControllerPluginManager');
$flashMessenger = $plugin->get('flashmessenger');
$messages = $flashMessenger->getMessages();
// Check for any recently added messages
if ($flashMessenger->hasCurrentMessages())
{
$messages += $flashMessenger->getCurrentMessages();
$flashMessenger->clearCurrentMessages();
}
return $messages;
}
And calling getMessages() from within the plugin should return an array of messages that can be passed to a partial and rendered.
Add code below to the view to render error messages:
<?php echo $this->flashmessenger()
->setMessageOpenFormat('<div class="alert alert-danger"><ul%s><li>')
->setMessageCloseString('</li></ul></div>')
->render('error')
; ?>
In previous request, make sure you created an error message by running code below in your controller:
$this->flashmessenger()->addErrorMessage('Whops, something went wrong...');
I have a custom module with optional text fields (shown via the standard text field option in system.xml). What I'd like to do is to show 1 mandatory text field and have a button that says something like [+ Add Field]. When that button is pressed, another text field is added. I'd like to do this for up to 10 total text fields (max). Can someone help me to accomplish this or point me to a nice tutorial on how to do this?
EDIT 7/10/12 # 11:30AM
I've been working on this and so far I can get the text fields to show up. However I have a few issues...
When pressing the "Save Config" button, none of the values entered in these dynamically created textfields actually save.
Is there a way to limit how many text fields actually save?
I'm unsure of the correct way to retrieve the text field(s) data. This is mostly due to the fact that I cannot save the values...(I will add another update after #1 is fixed if I need help with this...)
My System.xml file has this in it (directly related to this)..
<labels translate="label">
<label>This is some label</label>
<comment>This is some comment.</comment>
<tooltip><![CDATA[This is some tooltip]]></tooltip>
<frontend_type>text</frontend_type>
<frontend_model>Company_Namespace/adminhtml_textfields</frontend_model>
<backend_model>adminhtml/system_config_backend_serialized</backend_model>
<sort_order>50</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</labels>
My custom Textfields.php (frontend_model) file contents:
<?php
class Company_Namespace_Block_Adminhtml_Textfields extends Mage_Adminhtml_Block_System_Config_Form_Field
{
protected $_addRowButtonHtml = array();
protected $_removeRowButtonHtml = array();
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$this->setElement($element);
$html = '<div id="code_label_textfields_template" style="display:none">';
$html .= $this->_getRowTemplateHtml();
$html .= '</div>';
$html .= '<ul id="code_label_textfields_container">';
if ($this->_getValue('method')) {
foreach ($this->_getValue('method') as $i=>$f) {
if ($i) {
$html .= $this->_getRowTemplateHtml($i);
}
}
}
$html .= '</ul>';
$html .= $this->_getAddRowButtonHtml('code_label_textfields_container', 'code_label_textfields_template', $this->__('Button Label Here'));
return $html;
}
protected function _getRowTemplateHtml()
{
$html = '<li>';
$html .= '<div style="margin:5px 0 10px;">';
$html .= '<input class="input-text" name="'.$this->getElement()->getName().'" value="'.$this->_getValue('price/'.$i).'" '.$this->_getDisabled().'/> ';
$html .= $this->_getRemoveRowButtonHtml();
$html .= '</div>';
$html .= '</li>';
return $html;
}
protected function _getDisabled()
{
return $this->getElement()->getDisabled() ? ' disabled' : '';
}
protected function _getValue($key)
{
return $this->getElement()->getData('value/'.$key);
}
protected function _getSelected($key, $value)
{
return $this->getElement()->getData('value/'.$key)==$value ? 'selected="selected"' : '';
}
protected function _getAddRowButtonHtml($container, $template, $title='Add')
{
if (!isset($this->_addRowButtonHtml[$container])) {
$this->_addRowButtonHtml[$container] = $this->getLayout()->createBlock('adminhtml/widget_button')
->setType('button')
->setClass('add '.$this->_getDisabled())
->setLabel($this->__($title))
//$this->__('Add')
->setOnClick("Element.insert($('".$container."'), {bottom: $('".$template."').innerHTML})")
->setDisabled($this->_getDisabled())
->toHtml();
}
return $this->_addRowButtonHtml[$container];
}
protected function _getRemoveRowButtonHtml($selector='li', $title='Remove')
{
if (!$this->_removeRowButtonHtml) {
$this->_removeRowButtonHtml = $this->getLayout()->createBlock('adminhtml/widget_button')
->setType('button')
->setClass('delete v-middle '.$this->_getDisabled())
->setLabel($this->__($title))
//$this->__('Remove')
->setOnClick("Element.remove($(this).up('".$selector."'))")
->setDisabled($this->_getDisabled())
->toHtml();
}
return $this->_removeRowButtonHtml;
}
}
What am I missing, especially for saving values???
Refer to the system.xml and the Mage_GoogleCheckout_Block_Adminhtml_Shipping_Merchant block for an example. It's a little convoluted, but it works. You can see this in the Merchant Calculated settings in Google Checkout.