Magento: Referencing a custom block does not work - magento

I'm trying to reference a block from an other custom module to add a child block via layout file but it does not work.
The first layout file contains
<catalog_product_view>
<reference name="content">
<block type="core/template" name="tabcontainer" as="tabcontainer"
template="store/tabcontainer.phtml" >
<block type="catalog/product_list_related" name="kitparts"
template="store/product/kitparts.phtml"/>
</block>
</reference>
</catalog_product_view>
and in the second one I try to reference the tabcontainer block
<catalog_product_view>
<reference name="tabcontainer">
<block type="productshippinginfo/productshipping" name="productshippinginfo"
template="productshippinginfo/productshipping.phtml" after="kitparts"/>
</reference>
</catalog_product_view>
but the productshippinginfo block is not displayed while it is definitely included in the layout (using Alan Storm's layoutviewer plugin). If I reference content it is displayed.
What is wrong? Isn't it possible to add a child to a custom block from a custom extension?
Thanks for your help!
(I'm using Magento 1.6.1.0)
[edit]
in tabcontainer.phtml I'm calling <?php echo $this->getChildHtml(); ?>

First of all: Thank you Vinai!
Adding a dependency to control the loading order of my plugins it works!
in File: app/etc/modules/Company_ContentModule.xml
<Company_ContentModule>
<active>true</active>
<codePool>local</codePool>
<depends>
<Company_ContainerModule />
</depends>
</Company_ContentModule>
So the content module is loaded after the container module.

You are close. You just need to add this to you store/tabcontainer.phtml file:
getChildHtml('productshippinginfo'); ?>
The reason blocks that are children of "content" render without a template change is that the "content" block is a core/text_list block. If you look in Mage_Core_Block_Text_List, you will see that in its rendering method (_toHtml()) it renders its children.
You could also add an empty getChildHtml() call to your tabcontainer template to achieve a similar effect as a core/text_list - in fact, if you use getChildHtml('',false,true); you'll get the sorted children (set with before="" and after="" params).
EDIT: adjusted the getChildHtml() call syntax based on OP's comment correct findings that the first param must be an empty string a/o/t a boolean.

In the second layout I think you need to provide the nesting:
<catalog_product_view>
<reference name="content">
<reference name="tabcontainer">
<block type="productshippinginfo/productshipping" name="productshippinginfo"
template="productshippinginfo/productshipping.phtml" after="kitparts"/>
</reference>
</reference>
</catalog_product_view>
In order that maganto picks that up
And because you are doing
<?php echo $this->getChildHtml(); ?>
You do not need to specifically call it by name unless you want it to appear in a particular place in your HTML output.
In order to test if your block is appearing in the page at all add output="toHtml" in you block tag.
<block type="productshippinginfo/productshipping" name="productshippinginfo"
template="productshippinginfo/productshipping.phtml" after="kitparts" output="toHtml"/>

Related

How can I display a magento block in more than one location?

I'm trying to display the cross sell block in it's normal location as well as at the bottom of the page. There is more than one phtml template file involved so $this->getChildHtml does not work in the second location since the block is setup to only be on the cart.phtml file as of now.
In summary, how can I display the same block in more than one template file? I wan't to place these changes in my local.xml and do not want to modify core Magento template files.
The core layout directive for this block is set up as a child of the checkout.cart block:
<checkout_cart_index translate="label">
<!-- ... -->
<reference name="content">
<block type="checkout/cart" name="checkout.cart">
<!-- ... -->
<block type="checkout/cart_crosssell" name="checkout.cart.crosssell" as="crosssell" template="checkout/cart/crosssell.phtml"/>
</block>
</reference>
</checkout_cart_index>
To add it to the footer, you might need to only establish another parent-child relationship in your local.xml:
<checkout_cart_index>
<reference name="footer">
<action method="insert"><!-- or "append" to add to the end -->
<child>checkout.cart.crosssell</child>
</action>
</reference>
</checkout_cart_index>
This approach relies on the stock page/html/footer.phtml template which contains an empty getChildHtml() call, which causes it to render all child blocks.
Note that the footer block class Mage_Page_Block_Html_Footer has a never-expiring block_html cache lifetime, and it does not evaluate child contents for its cache entry. You may need to disable the cache for this block or rewrite the block class to account for the varied content of the crosssell block.

Magento - moving extension from left/right column to main

I try to move an ext: Customers who bought this product also purchased from default left/right column to main column under the product, but I don't know how to do this.
I try to change the line <product_detail_leftposition translate="label"> to <product_page translate="label"> in system.xml file but it doesn't help.
Any suggestions?
Thanks for any help!
You can do this by adding it to the Products view page section inside your layout XML. Add the block inside the content reference block, somewhere at the bottom.
Make sure it's inside the handle as this defines the structure used on the product view page.
app/design/frontend/[namespace]/[themename]/layout/catalog.xml
<catalog_product_view translate="label">
...
<reference name="content">
...
<block type="catalog/product_view" name="product.info" template="catalog/product/view.phtml">
<!-- Other blocks etc here.. add at the bottom -->
<block type="module/block" name="yourblock" as="yourblock" />
</block>
</reference>
</catalog_product_view>
This should automatically output the block for you if you add it in here, although that depends on the theme you are using.
if it doesn't automatically show, you may need to add a line to your view to display the block:
app/design/frontend/[namespace]/[themename]/template/catalog/product/view.phtml
<?php // use the block name used in the XML config.. ?>
<?php echo $this->getChildHtml('yourblock') ?>

Adding new cart block within local.xml - magento

Trying to add a new cart block to the header within local.xml this is what i have
<default>
<reference name="header">
<block type="checkout/cart_sidebar" name="cart_topbar" as="topCart" template="checkout/cart/top-cart.phtml"/>
</reference>
</default>
Then with in the header i call it with <?php echo $this->getChildHtml('topCart')?> however it shows nothing.
If i try changing the type to type="core/template" then the template will show the content. So this leads me to think i'm missing something specific to the checkout/cart_sidebar type?
The top-cart.phtml file simple contains a single text line to eliminate anything within that.
that's is your local.xml?
syntax is correct.
have you modify any thing else in Mage/Checkout/Block/Cart/Sidebar.php?

Cannot display block from template - magento

I'm calling a block from a template as follows. I'm aware it's not the recommended way but the layout.xml approach is giving me trouble
echo $this->getLayout()->createBlock('shoppingbasket/options')
->setTemplate('shoppingbasket/cart/item/default/options.phtml')
->setBlockId('options')
->setProduct($_item->getProduct())
->setSelectedOptions($this->getOptionList())
->toHtml() ?>
The block gets rendered. Now I'm trying to add it via the layout.xml approach
I've added the block to the layout.xml as follows:
<layout>
<checkout_cart_index>
<reference name="checkout.cart">
<block type="shoppingbasket/options" template="shoppingbasket/cart/item/default/options.phtml" name="options"></block>
<action method="addItemRender"><type>simple</type><block>checkout/cart_item_renderer</block><template>shoppingbasket/cart/item/default.phtml</template></action>
</reference>
</checkout_cart_index>
</layout>
and I'm calling the block from the template as follows:
<?php echo $this->getChildHtml('options') ?>
The block isn't appearing and I've tried moving the block everywhere in the layout.xml. What am I doing wrong? Also is there a way to pass parameters to the block using the layout.xml approach as I did with
->setProduct($_item->getProduct())
->setSelectedOptions($this->getOptionList())
Thanks!
you did everything right, except one thing: you should set block alias - "as" attribute of the block.
<block type="shoppingbasket/options" template="shoppingbasket/cart/item/default/options.phtml" name="options" as="options"></block>
Methods getChild or getChildHtml use block alias for retrieving block instance from layout.

Magento: Update block position with before/after attribute from local.xml layout reference

I need to append the before attribute to a block via a layout update reference call.
This is my local.xml file:
<?xml version="1.0"?>
<layout version="0.1.0">
<default>
<reference name="content">
<block type="page/html_wrapper" name="content.footer" as="contentFooter" translate="label" after="-">
<label>Content Footer</label>
<action method="setElementId"><value>content-footer</value></action>
<action method="setElementClass"><value>clear</value></action>
</block>
</reference>
</default>
<catalog_category_default>
<reference name="breadcrumbs.container">
<action method="unsetChild"><name>category.title</name></action>
</reference>
<reference name="content">
<block type="catalog/category_view" name="category.title" template="catalog/category/title.phtml" before="content.footer"/>
</reference>
</catalog_category_default>
</layout>
My problem is, on the content block I create a content.footer block that you can assign widgets to in admin. I use after="-" on the content.footer block so in my mind, should put it ALWAYS at the bottom of the content block but this is not the case.
When you view a catalog category and it inserts the category.products block in to the content block, it displays underneath the content.footer block. The only way to make it work is if I redefine it in my local.xml and include all the child blocks in category.products, and set before before="content.footer".
So I thought why can't I use a reference to category.products in the catalog_category_default layout and set the block's before attribute, I tried the following:
<reference name="category.products">
<action method="setBefore"><value>content.footer</value></action>
</reference>
Which had no affect.
I also noticed the setAttribute() function in Mage_Core_Block_Abstract which saw it's just a wrapper for setData() but thought I would try it anyway, still nothing:
<reference name="category.products">
<action method="setAttribute"><key>before</key><value>content.footer</value></action>
</reference>
Is it possible to do what I want? Does before/after only apply to blocks in the same reference?
Layout updates are processed in order of layout update handles. Your block is being added last to content but only for the default LUH. Other handles (catalog_product_view, catalog_category_layered, etc) are processed after this handle.
If you truly need a content footer everywhere and want to make sure that it is the last thing inside of the content div, you should add your block to the root node in the default handle and customize the root templates (directly under page/, e.g. page/1column.phtml) by adding a getChildHtml('your.block') call after the getChildHtml('content') call. This will ensure that your block is always immediately at the end of the content blocks.

Resources