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 */
Related
I'd like to add the categories description into the topmenu navigation on Magento.
I've tried a hack using CMS block but it didn't work properly (it shows category but outside of topmenu)
Do you have any any clue about how doing this easily?
Thanks for your help.
Quick summary: (Magento 1.8.2.0 and higher) (see last paragraph for earlier versions)
Add a child block under the top.menu block in your theme's local.xml and create (or copy from RWD theme) a custom renderer.phtml file to generate your custom menu HTML that includeds category descriptions.
The recommended path for renderer.phtml is app/design/frontend/yourpackage/default/template/page/html/topmenu/renderer.phtml.
Detail:
If you have Magento 1.8.2.0 or above you should seek to implement a menu renderer.phtml file due to this code:
file: app/Mage/Page/Block/Html/Topmenu.php
class: Mage_Page_Block_Html_Topmenu extends Mage_Core_Block_Template
function: getHtml()
public function getHtml($outermostClass = '', $childrenWrapClass = '')
{
//...
if ($renderer = $this->getChild('catalog.topnav.renderer')) {
$renderer->setMenuTree($this->_menu)->setChildrenWrapClass($childrenWrapClass);
$html = $renderer->toHtml();
} else {
$html = $this->_getHtml($this->_menu, $childrenWrapClass);
}
//...
}
You can see here that if there is a child block named catalog.topnav.renderer then Magento will use it, otherwise it falls back gracefully to use $this->_getHtml() where $this is Mage_Page_Block_Html_Topmenu.
Unfortunately the Magento default theme does not use the new renderer feature so there is not an example in the base theme. However the most excellent RWD theme which comes as standard with Magento does use the menu renderer and I highly recommend you study the RWD theme code to learn how to use a menu renderer phtml file.
Specifically you should create an additional entry in your local.xml to define your menu renderer:
file: app/design/frontend/yourpackage/default/layout/local.xml
<block type="page/html_header" name="header" as="header">
<block type="core/text_list" name="top.menu" as="topMenu" translate="label">
<label>Navigation Bar</label>
<block type="page/html_topmenu" name="catalog.topnav" template="page/html/topmenu.phtml">
<block type="page/html_topmenu_renderer" name="catalog.topnav.renderer" template="page/html/topmenu/renderer.phtml"/>
</block>
</block>
</block>
Or something like that to suit your theme layout. Noting specifically the all-important hard coded child block name name="catalog.topnav.renderer"
And then I would start with a copy of the RWD renderer.phml file copied into your theme path page/html/topmenu/renderer.phtml
file: app/design/frontend/rwd/default/template/page/html/topmenu/renderer.phtml
<?php
/** #var Mage_Page_Block_Html_Topmenu_Renderer $this */
/** #var Varien_Data_Tree_Node $menuTree */
/** #var string $childrenWrapClass */
$html = '';
$children = $menuTree->getChildren();
$parentLevel = $menuTree->getLevel();
$childLevel = is_null($parentLevel) ? 0 : $parentLevel + 1;
$counter = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter == 1);
$child->setIsLast($counter == $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = 'level'. $childLevel;
$_hasChildren = ($child->hasChildren()) ? 'has-children' : '';
$html .= '<li '. $this->_getRenderedMenuItemAttributes($child) .'>';
$html .= ''. $this->escapeHtml($this->__($child->getName())) .'';
if (!empty($childrenWrapClass)) {
$html .= '<div class="'. $childrenWrapClass .'">';
}
$nextChildLevel = $childLevel + 1;
if (!empty($_hasChildren)) {
$html .= '<ul class="level'. $childLevel .'">';
$html .= '<li class="level'. $nextChildLevel .' view-all">';
$html .= '<a class="level'. $nextChildLevel .'" href="'. $child->getUrl() .'">';
$html .= $this->__('View All') . ' ' . $this->escapeHtml($this->__($child->getName()));
$html .= '</a>';
$html .= '</li>';
$html .= $this->render($child, $childrenWrapClass); //THIS IS THE RECURSION
$html .= '</ul>';
}
if (!empty($childrenWrapClass)) {
$html .= '</div>';
}
$html .= '</li>';
$counter++;
}
return $html;
And by studying that file you can start to see where and how various modifications affect the menu html.
Please note the code that Mage_Page_Block_Html_Topmenu_Renderer::render() uses to handle your rendrerer.phtml file: unusually for Magento it is a direct include $this->_templateFile and either returns the string or the ob_get_cleaned buffer:
file: /app/code/core/Mage/Page/Block/Html/Topmenu/Renderer.php
class: Mage_Page_Block_Html_Topmenu_Renderer
function: render()
public function render(Varien_Data_Tree_Node $menuTree, $childrenWrapClass)
{
ob_start();
$html = include $this->_templateFile;
$directOutput = ob_get_clean();
if (is_string($html)) {
return $html;
} else {
return $directOutput;
}
}
If you are using a version prioir to 1.8.2.0 you will need to rewrite the class Mage_Page_Block_Html_Topmenu and override its function _getHtml() to inject your extra HTML into the menu. The main disadvantage being you need to recompile every time the menu layout changes.
Thank you for this answer.
Now It's Ok I display the topmenu from my template.
The thing that I don't really understand is how to get the description value.
Does the
$children = $menuTree->getChildren();
object contain the description ?
I've tried to call it with $child->getDescription() but it did not work.
I want my error, warning, notification messages on frontend to extend a bit. So,
I need to override
Mage_Core_Block_Messages
class's
public function getGroupedHtml()
{
$types = array(
Mage_Core_Model_Message::ERROR,
Mage_Core_Model_Message::WARNING,
Mage_Core_Model_Message::NOTICE,
Mage_Core_Model_Message::SUCCESS
);
$html = '';
foreach ($types as $type) {
if ( $messages = $this->getMessages($type) ) {
if ( !$html ) {
$html .= '<' . $this->_messagesFirstLevelTagName . ' class="messages">';
}
$html .= '<' . $this->_messagesSecondLevelTagName . ' class="' . $type . '-msg">';
$html .= '<' . $this->_messagesFirstLevelTagName . '>';
foreach ( $messages as $message ) {
$html.= '<' . $this->_messagesSecondLevelTagName . '>';
$html.= '<' . $this->_messagesContentWrapperTagName . '>';
$html.= ($this->_escapeMessageFlag) ? $this->htmlEscape($message->getText()) : $message->getText();
$html.= '</' . $this->_messagesContentWrapperTagName . '>';
$html.= '</' . $this->_messagesSecondLevelTagName . '>';
}
$html .= '</' . $this->_messagesFirstLevelTagName . '>';
$html .= '</' . $this->_messagesSecondLevelTagName . '>';
}
}
if ( $html) {
$html .= '</' . $this->_messagesFirstLevelTagName . '>';
}
return $html;
}
to extend the html and put a cross in the message box and implement Jquery. logic: on click close hide error box. So customers can upon click hide the box.
I believe this class doesn't have any template file and the html it is rendering from the this block class itself as I can see in getGroupedHtml() method.
So, I am going to override this method and add more html.
Also, I want to do this only for one theme and not in Admin
What is the better way to achieve this?
Please suggest me something. Thanks
You could accomplish this without overriding anything and by just going for JavaScript (jQuery) only.
Here is a simple script that should do the job.
var messages = jQuery("ul.messages li[class$='-msg']");
messages.each(function(){
var message = jQuery(this);
message.find('span').append('<span class="close">X</span>');
});
messages.on('click', function(){
var message = jQuery(this).closest("li[class$='-msg']");
message.hide();
});
The script adds a 'X' to the end of every message and removes (hides) the message when it's clicked.
The only thing left to do is to give the cross (span X) some styling.
You could place this in your footer template for the correct theme.
how do make it so that when I edit an entry, the correct value for my custom field type is selected? I have this so far:
class JFormFieldCustom extends JFormField {
protected $type = 'Custom';
// getLabel() left out
public function getInput() {
return '<select id="'.$this->id.'" name="'.$this->name.'">'.
'<option value="1" >1</option>'.
'<option value="2" >2</option>'.
'</select>';
}
}
How do I pass the selected value to this class so I can do:
<option value="1"SELECTED>1</option>
or
<option value="2" SELECTED>2</option>
Thanks!
It's easier to use what's already there, i.e. extend JFormFieldList in place of JFormField, then all you have to do is return the option's for your list. The inherited functionality will do the rest for you - including selecting the option that matches $this->value
<?php
/**
* Do the Joomla! security check and get the FormHelper to load the class
*/
defined('_JEXEC') or die('Restricted Access');
JFormHelper::loadFieldClass('list');
class JFormFieldMyCustomField extends JFormFieldList
{
/**
* Element name
*
* #var string
*/
public $type = 'MyCustomField';
/**
* getOptions() provides the options for the select
*
* #return array
*/
protected function getOptions()
{
// Create an array for our options
$options = array();
// Add our options to the array
$options[] = array("value" => 1, "text" => "1);
$options[] = array("value" => 1, "text" => "1);
return $options;
}
}
Use $this->value to get selected value.Try this-
class JFormFieldCustom extends JFormField {
protected $type = 'Custom';
// getLabel() left out
public function getInput() {
return '<select id="'.$this->id.'" name="'.$this->name.'">'.
'<option value="1" <?php echo ($this->value==1)?'selected':''?>>1</option>'.
'<option value="2" <?php echo ($this->value==2)?'selected':''?>>2</option>'.
'</select>';
}
}
Hope this will help.
Select for Joomla
http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
* #copyright (c) 2017 YouTech Company. All Rights Reserved.
* #author macasin
*/
defined('_JEXEC') or die;
JFormHelper::loadFieldClass('list');
class JFormFieldSelect extends JFormFieldList
{
protected $type = 'select';
protected function getInput()
{
$html = array();
$attr = '';
// Initialize some field attributes.
$attr .= !empty($this->class) ? ' class=select ' . $this->class . '"' : ' class=select ';
$attr .= $this->readonly ? ' readonly' : '';
$attr .= $this->disabled ? ' disabled' : '';
$attr .= !empty($this->size) ? ' size="' . $this->size . '"' : '';
$attr .= $this->required ? ' required aria-required="true"' : '';
// Initialize JavaScript field attributes.
$attr .= $this->onchange ? ' onchange="' . $this->onchange . '"' : '';
// Get the field options.
$options = $this->getOptions();
// Load the combobox behavior.
JHtml::_('behavior.combobox');
$html[] = '<div class="select input-append">';
// Build the input for the combo box.
$html[] = '<select name="' . $this->name . '" id="' . $this->id . '" value="'
. htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '"' . $attr . ' autocomplete="off" >';
foreach ($options as $option)
{
$html[] = '<option '.($option->value == $this->value ? "selected" : "").' value='.$option->value.'>' . $option->text . '</option>';
}
$html[] = '</select></div>';
return implode($html);
}
}
I have customized the new style for meagento notification messages in below path /app/code/core/Mage/Core/Block/Messages.php
Below Code is i have customized
public function getGroupedHtml()
{
$types = array(
Mage_Core_Model_Message::ERROR,
Mage_Core_Model_Message::WARNING,
Mage_Core_Model_Message::NOTICE,
Mage_Core_Model_Message::SUCCESS
);
$html = '';
foreach ($types as $type) {
if ( $messages = $this->getMessages($type) )
{
foreach ( $messages as $message )
{
$html.= '<div class="ml-alert-2-'.$type.'">';
$html.= '<div class="style-2-icon '.$type.'"></div>';
$html.= ($this->_escapeMessageFlag) ? $this->htmlEscape($message->getText()) : $message->getText();
$html.= '<div class="style-2-close '.$type.'" onclick="this.parentNode.parentNode.removeChild(this.parentNode);"></div>';
$html.= '</div>';
}
}
}
return $html;
}
I have replaced the Default Magento theme in above function, The Notification Theme Works fine in Fron-end, But The Admin panel Notification Themes not applied..
So How to find the message type like (Admin message,Front-end message) in above function?
Please suggest me ?
Thanks All.
The frontend and backend messages are handled by different block classes. The code you are editing is only used in the frontend of Magento. If you wish to customise the Backend messages you will need to edit/overload a different class, namely Mage_Adminhtml_Block_Messages (which is located in /app/code/core/Mage/Adminhtml/Block/Messages.php).
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.