1

NOTE

Due to the successful outcome of this thread, the documentation at the provided link has been updated. It no longer contains the incomplete information as described.

I'm having an issue taking viewlets that appear in the plone.portalheader viewletManager and adding them to specific locations (not utilizing the linear concatenation). My goal is to make the html code look identical to my html template mockup. I do not want nor require the viewlets to change positions and I would like to see a couple of those elements wind up in the same overarching markup.

I have been reading the following documentation, but it seems to be in conflict with my set up (which is Plone 4.1):

http://collective-docs.readthedocs.org/en/latest/views/viewlets.html#rendering-viewlets-with-accurate-layout

I'm not sure if that particular page is outdated or incorrect (it looks like most references to "tab" were replaced with spaces. eg, <table> is now < le>) or if I'm doing something wrong (which I wouldn't put it past me).

It looks like when I want to call the new header created from the example, citing something.header fails inside my portal_header.pt file. If someone can eyeball the example and let me know if there are any important parts missing, that would be a huge help to me.

Including my code:

theme/browser/configure.zcml (portion):

<!-- The portal header -->
<browser:viewlet
    name="plone.header"
    manager="plone.app.layout.viewlets.interfaces.IPortalTop"
    layer=".interfaces.IThemeSpecific"
    class=".header.HeaderViewlet"
    template="templates/portal_header.pt"
    permission="zope2.View"
    />

theme/browser/templates/portal_header.pt:

<header>
    <div class="container_12">
        <div tal:replace="structure provider:theme.header" />
    </div>
</header>

theme/browser/header.py:

from Acquisition import aq_inner
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone.app.layout.viewlets import common as base
#import plonetheme.something.browser.viewlets.common as something #left over from original article

def render_viewlet(factory, context, request):
    context = aq_inner(context)
    viewlet = factory(context, request, None, None).__of__(context)
    viewlet.update()
    return viewlet.render()


class HeaderViewlet(base.ViewletBase):
    index = ViewPageTemplateFile('header_items.pt')

    def update(self):
        base.ViewletBase.update(self)
        self.subviewlets = {}

    def renderViewlet(self, viewlet_class):
        return render_viewlet(viewlet_class, self.context, self.request)


    def render(self):
        self.subviewlets["logo"] = self.renderViewlet(base.LogoViewlet)
        self.subviewlets["search"] = self.renderViewlet(base.SearchBoxViewlet)
        return self.index()

theme/browser/header_items.pt:

<header>
    <div class="container_12">
<div tal:replace="structure view/subviewlets/logo" />

<div tal:replace="structure view/subviewlets/search" />
    </div>
</header

That's all I have modified per the article I listed above. I'm unsure if I should modify viewlets.xml.

From what I understand of the article, it wants to override and replace the plone.portalheader in portal_header.pt with theme.header by utilizing the class provided in header.py. However, I'm not modifying viewlets.xml which is where I believe the problem lies. Or it could like with the fact that I'm replacing plone.portalheader with theme.header and I'm not changing the name of the viewlet in configure.zcml from plone.header to theme.header.

I've tried a whole bunch of permutations on what I believe to be the solution and I can't get anything to work, even trying to modify viewlets.xml.

When I follow the example I get an error message that says:

ContentProviderLookupError(u'theme.header',)
Community
  • 1
  • 1

1 Answers1

2

TAL provider: expression will only render portlet managers or viewlet managers. It does not work with viewlets. That's why there is render_viewlet(factory, context, request) shortcut in the example.

What you want to is to

  • create a viewlet which contains all of your layout (done, HeaderViewlet)

  • place this viewlet in good known viewlet manager (use /@@manage-viewlet to figure out which) - this is not done

  • then in this new viewlet render subviewlets as you do

If you need to create a new viewlet manager (ugh, pain in the ass and shitty job) you can follow instructions here:

http://opensourcehacker.com/2011/11/29/creating-a-viewlet-manager-in-plone/

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • I was able to successfully follow these steps to fix my problem. My problem, as you pointed out, was that I was not properly adding my new viewlet to the proper viewlet manager. To rectify that, I changed the `manager` attribute in my `browser:viewlet` to reflect a new viewlet manager. When I did that, my templates weren't rendering. I needed to adjust the `class` attribute in the necessary viewlets to accomodate an extra python script that would adjust the template path of my modified viewlets. – Robert Longo Feb 02 '12 at 20:43
  • It looks like when you do it the way I had been using, I was in essence overriding the template attribute when I was calling in the common class in `plone.app.layout.viewlets.common.[class]` and needed to create a subclass to rectify that problem. I had come across this in the past, but was able to remedy the solution with your help. Thanks again. – Robert Longo Feb 02 '12 at 20:44
  • Please feel free to clean-up the viewlet doc to make this more obvious for others who might attempt to do the same :) – Mikko Ohtamaa Feb 02 '12 at 23:06
  • The one you link in your question, so that it would be little more clear – Mikko Ohtamaa Feb 04 '12 at 01:04
  • Glad to help. I will update the main post to reflect the changed information at the provided link. – Robert Longo Feb 06 '12 at 21:54