I'm working on a module in which we have a configuration as "advanemenu/general/enabled"
By using this config I am being able to add items conditionally to my magento frontend.
Ex.
<reference name="head">
<action method="addItem" ifconfig="advancemenu/general/enabled"><type>skin_css</type><name>css/advancemenu.css</name></action>
</reference>
Now similarly I want to remove the top navigation if the config value is enabled.
I tried the following but without any result...
<remove ifconfig="advancemenu/general/enabled" name="catalog.topnav" />
Incase the ifconfig works with <action> then is there any way to remove top navigation using this method.
Please help me if anyone knows how to do this.
(Thnx in Advance)
IfConfig only work with action method. When you call action in a xml layout this parse in a call to funcion in the block instance.
you can see this in:
file: app/code/core/Mage/core/Model/layout.php around line 289
protected function _generateAction($node, $parent)
{
if (isset($node['ifconfig']) && ($configPath = (string)$node['ifconfig'])) {
if (!Mage::getStoreConfigFlag($configPath)) {
return $this;
}
}
but a posible solution for this is add a template only in case of true value. For example
<reference name="head">
<action method="setTemplate" ifconfig="advancemenu/general/enabled">
<template>route/to/template</template>
</action>
</reference>
then, only when you have enable your module, you have template associate to this block, in another case, your block don´t have template, then don´t load.
You can remove any block using the unsetchild method.
For the above case
<reference name="top.menu">
<action method="unsetChild" ifconfig="advancemenu/general/enabled">
<name>catalog.topnav</name>
</action>
</reference>
It will help for the conditional remove statement.
Related
I'm trying to change the top links list on header, such as addLink, removeLink, etc. So I create an observer which catch event "controller_front_send_response_before", and add this:
$layout = $this->getLayout();
$layout->getBlock('top.links')->addLink('hi','test','the');
But the top links stay the same. It worked if I do it in layout xml file like this:
<default>
<reference name="top.links">
<action method="addLink">
<label>hi</label>
</action>
</reference>
</default>
Please help, I need to do it programmatically, so I can add some conditions.
use this event controller_action_layout_generate_blocks_after
I need to change category and product view for each category/product, for change category list I have add into local.xml:
<layouts>
<CATEGORY_3>
<reference name="product_list">
<action method="setTemplate">
<name>catalog/product/list-1.phtml</name>
</action>
</reference>
</CATEGORY_3>
</layouts>
but I don't know how to change layout from product of category_3, I try adding
<reference name="product.info">
<action method="setTemplate">
<action method="setTemplate">
<template>catalog/product/view-1.phtml</template>
</action>
</action>
</reference>
inside tag but nothing, where is the mistake?
First off, your second XML config block seems to be missing a .phtml extension inside <template></template>.
Second, your action method="setTemplate" is nested twice. Remove the first one
<reference name="product.info">
<!-- action method="setTemplate" REMOVED-->
<action method="setTemplate">
<template>catalog/product/view-1.phtml</template>
</action>
<!-- /action REMOVED-->
</reference>
Also the template you're trying to call
Additionally, Please don't do this from local.xml. You will have caching issues. I guarantee it. This is probably one of the reasons why you're not seeing changes. We did a similar thing last month and it bit us in the arse.
Instead go to Catalog > Manage Categories > (Click on/Select a Category) > Custom Design Tab and then enter your XML layout changes at the Custom Layout Update box. This worked for us better and thus it might give you a better chance of success, too.
I am trying to change checkout/cart.phtml through layout update in my module's layout file i.e. mymodule.xml
<layout>
<checkout_cart_index>
<reference name="checkout.cart">
<action method="setCartTemplate"><value>mymodule/checkout/cart.phtml</value></action>
</reference>
</checkout_cart_index>
</layout>
But It is not working. Any clues?
Ankita, What I'm about to write is the actual way to get what you want. While the official answer by John Hickling will work, it is not how Magento intended the main cart template to be modified.
Magento deliberately chose to use different methods for setting the cart templates, namely, setCartTemplate and setEmptyTemplate. They can be seen in Magento's own app/design/frontend/base/default/layout/checkout.xml. This was done so that two templates can be managed, each to handle their own condition. The first condition is for a cart with items, while the second condition is for a cart without items. By using the common setTemplate method, that distinction will be lost: a cart with items and a cart without items will both display the same template. This is no good.
You were so close. You were correct in trying to use the setCartTemplate method. That is what you should be using. However, you were missing one essential method call that would allow Magento to even consider using it: you forgot to include the chooseTemplate method call. Note Magento's own checkout.xml file:
<block type="checkout/cart" name="checkout.cart">
<action method="setCartTemplate"><value>checkout/cart.phtml</value></action>
<action method="setEmptyTemplate"><value>checkout/cart/noItems.phtml</value></action>
<action method="chooseTemplate"/>
Look at that last method call, chooseTemplate. If you look in app/code/core/Mage/Checkout/Block/Cart.php you will see the following method, within which those familiar setCartTemplate and setEmptyTemplate methods are called, but because they are magic methods, they are not easily searchable in Magento's source, which is problematic for a lot of people:
public function chooseTemplate()
{
$itemsCount = $this->getItemsCount() ? $this->getItemsCount() : $this->getQuote()->getItemsCount();
if ($itemsCount) {
$this->setTemplate($this->getCartTemplate());
} else {
$this->setTemplate($this->getEmptyTemplate());
}
}
You were missing that chooseTemplate method call. This is what your own layout XML file should look like:
<checkout_cart_index>
<reference name="checkout.cart">
<action method="setCartTemplate"><value>mymodule/checkout/cart.phtml</value></action>
<action method="setEmptyTemplate"><value>mymodule/checkout/noItems.phtml</value></action>
<action method="chooseTemplate"/>
</reference>
</checkout_cart_index>
I recommend you update your code if it is still under your control. This is how Magento intended the cart templates to be updated. The common setTemplate method is too destructive for this task. Granularity was Magento's intention, so updates should maintain that granularity. I also recommend you mark this as the correct answer.
The method is setTemplate not setCartTemplate, like so:
<layout>
<checkout_cart_index>
<reference name="checkout.cart">
<action method="setTemplate"><value>mymodule/checkout/cart.phtml</value></action>
</reference>
</checkout_cart_index>
</layout>
Let me preface this question by declaring my newbie status when it comes to front end development...
I'm writing an admin module with a new screen in the admin panel, consisting of a number of tabs. Each tab is added using the $this-addTab(...) function in a Tabs.php file e.g.
$this->addTab('form_products', array(
'label' => Mage::helper('mymodule')->__('All The Products'),
'title' => Mage::helper('mymodule')->__('All The Products'),
'content' => $this->getLayout()->createBlock ('mymodule/adminhtml_something_edit_tab_productsform')->toHtml(),
));
This tab has a list of products, with a checkbox field populated via a function getSelectedProducts(). The block file for this tab extends Mage_Adminhtml_Block_Widget_Grid
I see from core Magento that you use a declaration something like the following to declare the hidden field name and data callback function :
<block type="adminhtml/widget_grid_serializer" name="related_grid_serializer">
<reference name="related_grid_serializer">
<action method="initSerializerBlock">
<grid_block_name>catalog.product.edit.tab.related</grid_block_name>
<data_callback>getSelectedRelatedProducts</data_callback>
<hidden_input_name>links[related]</hidden_input_name>
<reload_param_name>products_related</reload_param_name>
</action>
<action method="addColumnInputName">
<input_name>position</input_name>
</action>
</reference>
</block>
My question is, is it possible to declare the hidden input name and callback function etc. during construction of the block within the php?
If not, then I need help with the layout xml.......
At the moment my layout.xml file looks like:
<?xml version="1.0"?>
<layout version="0.1.0">
<mymodule_adminhtml_something_index>
<reference name="content">
<block type="mymodule/adminhtml_something" name="something" />
</reference>
</mymodule_adminhtml_something_index>
</layout>
I have tried adding a nested block declaration within this e.g.
<?xml version="1.0"?>
<layout version="0.1.0">
<mymodule_adminhtml_something_index>
<reference name="content">
<block type="mymodule/adminhtml_something" name="something" />
<block type="mymodule/adminhtml_something_edit_tab_productsform" name="mymodule.adminhtml.something.edit.tab.productsform"/>
<block type="adminhtml/widget_grid_serializer" name="something_grid_serializer">
<reference name="something_grid_serializer">
<action method="initSerializerBlock">
<grid_block_name>mymodule.adminhtml.something.edit.tab.productsform</grid_block_name>
<data_callback>getSelectedProducts</data_callback>
<hidden_input_name>links[selected]</hidden_input_name>
<reload_param_name>products_selected</reload_param_name>
</action>
</reference>
</block>
</reference>
</mymodule_adminhtml_something_index>
</layout>
The above errors, as it is loading my block file at the same time as main block file (which obviously is not correct). I have messed around with nesting the blocks above, and declaring in seperate tags e.g.
<mymodule_adminhtml_something_edit_form>
The driving force behind this is trying to get the data of any checkboxes selected on the products form posted back when the form is saved, which at the moment is not happening.
You need to know that <action method=...> in layout files is just calling the named method on the instantiated block.
In the above example related_grid_serializer is an object of Mage_Adminhtml_Block_Widget_Grid_Serializer and that this,
<action method="initSerializerBlock">
<grid_block_name>catalog.product.edit.tab.related</grid_block_name>
<data_callback>getSelectedRelatedProducts</data_callback>
<hidden_input_name>links[related]</hidden_input_name>
<reload_param_name>products_related</reload_param_name>
</action>
is exactly equivalent to:
->initSerializerBlock('catalog.product.edit.tab.related',
'getSelectedRelatedProducts',
'links[related]',
'products_related');
You can call that method directly from your own class.
(Note the <grid_block_name>, <data_callback>, <hidden_input_name> and <reload_param_name> tag names are ignored. They exist for readability reasons only.)
Previously in Magento, the wishlist link was added using the following (in wishlist.xml):
<action method="addWishlistLink"></action>
And you could override that and remove it using the following (in your local.xml):
<remove name="wishlist_link"/>
However, in the newest Magento, 1.4.2, they've changed how the wishlist link is added to the following:
<action method="addLinkBlock"><blockName>wishlist_link</blockName></action>
Anyone know how to remove the wishlist link now they’ve changed how it’s added?
It appears there's no publicly available way to reliably remove the wishlist link block from the layout. (you can skip to the end for a workaround)
The addLinkBlock assumes the presence of the block that's been passed, so using remove in the way you describe results in a fatal error being thrown
Fatal error: Call to a member function getPosition() on a non-object in /Users/alanstorm/Sites/magento1point4.2.dev/app/code/core/Mage/Page/Block/Template/Links.php on line 112
Here's the core code that causes that error
app/code/core/Mage/Page/Block/Template/Links.php
public function addLinkBlock($blockName)
{
$block = $this->getLayout()->getBlock($blockName);
$this->_links[$this->_getNewPosition((int)$block->getPosition())] = $block;
return $this;
}
This method assumes its going to be able to pull out a block by whatever name gets passed, so we can't just remove the wishlist_link block as we could in previous versions.
The only mechanism for removing a link appears to be the following method on the same block class
app/code/core/Mage/Page/Block/Template/Links.php
public function removeLinkByUrl($url)
{
foreach ($this->_links as $k => $v) {
if ($v->getUrl() == $url) {
unset($this->_links[$k]);
}
}
return $this;
}
However, this is done using string comparison, and there's no reliable way (that I know of) to generate a URL Object from a layout file, cast it as a string, and pass it into the method (this would be required, as there are numerous configuration settings that can change what the final string URL will be). That makes this method not helpful for our needs.
So, what we can do it modify the existing wishlist_link block to use a blank or non-existant template. This way the block still renders, but it renders as an empty string. The end result is we avoid the fatal error mentioned above, but still manage to remove the link from our selected pages.
The following would remove the link from all the pages using the default handle.
<!-- file: local.xml -->
<layout>
<default>
<reference name="wishlist_link">
<action method="setTemplate"><template>blank-link.phtml</template></action>
</reference>
</default>
</layout>
In your local.xml file,
<?xml version="1.0"?>
<layout version="0.1.0">
<default>
<reference name="root">
<reference name="top.links">
<!-- Remove wishlist link in magento 1.4.x and newer -->
<remove name="wishlist_link"/>
</reference>
</reference>
</default>
</layout>
You can remove the wishlist link from the admin panel System > Configuration > Wishlist > Enabled = "No"
Add the following to your local.xml file.
<reference name="top.links">
<remove name="wishlist_link"/>
</reference>
This works! I have removed Wishlink from Toplinks and wanted to add it back into another block but that doesn't seem possible when you remove it in this way. Sadly.
I know I'm years late here, but for all of those people who are still looking for answers to this.
I have a way to work around this issue that is only a bit of extra work but it's not hacky and it gives you FULL control of your top.links block.
Simply unset the top.links block and re-create it, it will be empty (no more wishlist_link block) and all you have to do is add whichever links you want inside of it! (Do all of this in your theme/layout/local.xml file of course).
<layout version="0.1.0">
<default>
<!-- HEADER -->
<reference name="header">
<!-- Unsetting the already existing top links block -->
<action method="unsetChild">
<name>topLinks</name>
</action>
<!-- Re-creating a new top links block -->
<block type="page/template_links" name="top.links" as="topLinks">
<!-- EXAMPLE: Account Dashboard Link -->
<action method="addLink" translate="label title" module="catalog">
<label>Account Dashboard</label>
<url helper="customer/getAccountUrl"/>
<title>Account Dashboard</title>
</action>
<!-- You can add any other links that you want -->
</block>
</reference>
</default>
</layout>
Also remember that for some links like Sign In and Log Out you will need to reference your top.links block inside the appropriate <customer_logged_out> and <customer_logged_in> handles instead of inside of <default> as a guide for this you can look at Magento's customer.xml file.
IMPORTANT: If there are any modules included in your project that add links to the top.links block, those links won't show up because local.xml is processed last, so just keep that in mind when using this method :)
I am a Certified Magento Front End Developer with over 3 years of experience and I have overcome LOTS of layout XML headaches to the point where we became best friends.