How to print attributes of related objects in zope templates? - plone

I wrote an dexterity type with a field relating to another object:
institution = RelationChoice(
title=_(u"Institution"),
source=ObjPathSourceBinder(
object_provides=IInstitution.__identifier__
),
)
And also in the template I wrote:
<span id="institution" tal:content="context/institution" />
But it prints:
<z3c.relationfield.relation.RelationValue object at 0xe3a032c>
I have tried to get attributes to build a link to the item, but the next doesn't works:
<span id="institution" tal:content="context/institution/absolute_url" />
How can I get the attributes of the objecto to make a link to it?

Reference objects are documented in the Dexterity developer manual. You are looking for the to_object attribute:
<span id="institution" tal:content="context/institution/to_object/absolute_url" />
which would insert the URL of the linked object, or you could show the Title instead:
<span id="institution" tal:content="context/institution/to_object/Title" />

Related

Show News Item creator or owner full name in Plone

I'm trying to show the full name for each news item in a list. For the moment I have only the user id (nickname).
Is there a simple way (in existing .pt file) to show the full name of creator or owner instead of a nickname?
The page must work for anonymous users, too. I mean - the page must be public.
Some details:
<div class="container-fluid news-list-container"
tal:define="news_items python:context.getFolderContents(contentFilter={'portal_type':['News Item'], 'sort_on': 'Date', 'sort_order': 'descending',});
Batch python:modules['Products.CMFPlone'].Batch;
b_size python:4;
b_start python:0;
b_start request/b_start | b_start;
batch python:Batch(news_items, b_size, int(b_start), orphan=0);"
tal:condition="news_items">
<div class="news-list-items">
<tal:items tal:repeat="news_item batch">
<!-- News item -->
<div class="row news-item"
tal:define="news_object python:news_item.getObject();
news_date python:news_object.getField('modification_date').getAccessor(news_object)();
news_title python:news_object.getField('title').getAccessor(news_object)();
news_description python:news_object.getField('description').getAccessor(news_object)();
news_image python:news_object.getField('image').getAccessor(news_object)();
news_url python:news_object.absolute_url();
news_creators python:news_object.getField('creators').getAccessor(news_object)(); .... ...
<tal:fullname define="membership context/portal_membership;
info python:membership.getMemberInfo(user.getId());
fullname info/fullname">
You are are <span class="name" tal:content="fullname" />
</tal:fullname>
This example is taken from the plone documentation
You can get inspired a lot by this code:
https://github.com/collective/Products.Scrawl/blob/1021047c4ef6c2655d104e8b345a24140da9e4aa/Products/Scrawl/browser/blogentry_view.pt#L32
<tal:name tal:condition="item_creator"
tal:define="author python:context.portal_membership.getMemberInfo(item_creator)">
<span i18n:translate="label_by_author">Posted by
<a href="#"
title="Read more posts by this author"
tal:attributes="href string:${context/portal_url}/author/${item_creator}"
tal:content="python:author and author['fullname'] or item_creator"
tal:omit-tag="not:author"
i18n:domain="scrawl"
i18n:name="author"
i18n:attributes="title author_title">
Bob Dobalina
</a>
</span>
</tal:name>
Mind the possible performance issues.
A cached view method may work a lot better, e.g.:
#memoize
def userid2fullname(self, userid):
pm = api.portal.get_tool('portal_membership')
memberinfo = pm.getMemberInfo(userid)
return memberinfo and memberinfo['fullname'] or userid

thymeleaf how to get an input backing bean generated name attribute

Is it possible with thymeleaf to retrieve an input "generated" name attribute ?
I need to create a div with an id equals to an input name attribute.
Input names are generated via the th:field.
Markup:
<input type="radio" id="winterTiresInstalled" th:field="*{winterTiresInstalled.value}" />
Generated markup:
<input id="fld_winterTires" type="radio" name="vehicle.winterTiresInstalled.value" />
What I want :
<div th:id="???" />
to obtain :
<div id="vehicle.winterTiresInstalled.value" />
So, how can I retrieve the generated name attribute value "vehicle.winterTiresInstalled.value" with thymleaf ?
I could do it in js but I would prefer doing it in my template.
Thank you.
David
th-attr is best suited for this use case.
<a href="#" th:attr="data-id=${object.getId()}, data-name=${object.getName()}"/>
The above will result is something like this(haven't tested)
<a href="#" data-id="420" data-name="user-link"/>
Did the solution in javascript for now. I change the id of div after the page loads.
I would prefer do it directly in my template but can't figure out a way to do it with thymeleaf.

Capybara Element not found error even though the element exists

I am writing a selenium test with capybara and trying to fill out a pop-up box. I am not able to fill in the name of the element using fill_in method in capybara. This works perfectly fine with other forms in other pages but not on this one.
Here is my test code:
describe "Jobs" do
before do
login(users(:admin))
end
it "creates a job on a workspace" do
visit('#/workspaces')
click_button "Create Workspace"
within_modal do
fill_in 'name', :with => "testing-jobs"
click_button "Create Workspace"
end
click_link "Dismiss the workspace quick start guide"
page.should have_content('All Activity')
Workspace.find_by_name("testing-jobs").should_not be_nil
click_link "Jobs"
click_button "Create"
within('#facebox') do
find(".name").click
fill_in '. name', :with => "real job"
choose "onDemand"
click_button "Create"
end
page.should have_content "real job"
end
end
The first fill_in with respect to workspace works really fine but when I get to the jobs it just screws up.
Here is the actual dev code from firebug:
<div id="facebox" class="dialog_facebox" style="top: 30px; left: 424.5px;">
<div class="popup" style="max-height: 626px;">
<div class="content">
<div class="configure_job_dialog dialog">
<div class="dialog_header">
<div class="errors"></div>
<div class="dialog_content" data-template="configure_job_dialog">
<form action="#">
<label class="required">Name</label>
<input class="name" type="text" value="">
I am using the name class in the fill_in method but capybara is not catching it. I tried to debug a little more to see why my workspace gets created but not the job. The workspace code is as follows.
<input type="text" maxlength="256" tabindex="1" placeholder="Name this workspace" name="name">
Any help is highly appreciated.
Problem
Based on the html given, you will not be able to use the fill_in method. The reasons are that:
The fill_in method locates elements based on their id attribute, name attribute or label text. It does not support locating elements by a CSS-selector, which .name is.
The element does not have an id or name attribute and therefore cannot be used by fill_in. As well, the label is not directly associated with the input via for and id attributes. I believe fill_in only checks explicit labels (rather than implicit labels).
Note that the fill_in works for the workspace because that input has a name attribute specified.
Solution
The ideal solution would be to update the input to have an id attribute, name attribute or explicit label. However, if that is not possible or if you need to use the CSS-selector, you can find the element and then set the value:
find('.name').set("real job")

Thymeleaf - custom attribute

I need to set custom attribute (data-validation-matches-message) value from messages resources.
<input data-validation-matches-message="Text from messages resources" />
I can receive and print messages resources value as:
<p th:text="#{user.notfound}"></p>
But how I can set this value for a custom attribute (data-validation-matches-message)?
UPD (I use this)
<input th:attr="data-validation-matches-message=#{user.notfound}"/>
Since Thymeleaf 2.1 you can do this:
<a data-th-attr="data-groupid=${somevalue}, data-groupname=${someothervalue}">...</a>
source
Try this:
<input th:attr="data-validation-matches-message='\'' + #{user.notfound}" + '\''"/>
Using 3.0.9.RELEASE:
<td th:text="${item.description}" th:attr="width=${isSplit} ? '44%' : '59%'" />
This will add width="44%" or width="59%according to a boolean set in the variables.
width might as well have been any other custom attribute.

Condition depending other field

i have 2 fields (fieldA and fieldB)
what i want :
- if the fieldA contains something then the fieldB should not be displayed
what i try :
<span tal:replace="here/getFieldA" />
<span tal:omit-tag="here/getFieldA" tal:replace="here/getFieldB" />
so it doesn't work
thanks for your help
What you are looking for is tal:condition, possibly combined with the not: and exists: prefixes:
<span tal:replace="here/getFieldA" />
<span tal:condition="not:exists:here/getFieldA" tal:replace="here/getFieldB" />
Alternatively, you can use the | operator, which acts like an if operator, testing existence of the first element. If it doesn't exist, it'll use the next expression, and so on:
<span tal:replace="here/getFieldA | here/getFieldB" />
The tal:omit-tag attribute means something very different. If it's expression evaluates to True, then the tag, and only the tag itself, is omitted from the output. This is best illustrated with an example:
<span tal:omit-tag="">
<i>This part will be retained</i>
</span>
Rendering that piece of pagetemplate results in:
<i>This part will be retained</i>
The surrounding <span> tag was omitted, but the contents were preserved.
Try
<span tal:condition="here/getFieldA" tal:replace="here/getFieldB" />
The Zope Page Templates Reference http://docs.zope.org/zope2/zope2book/AppendixC.html
This is a refinement of the original answer, based on the comments:
<tal:block
tal:define="zone here/getZoneintervention;
thezone python:', '.join(zone);
dep here/getDepartements;
thedep python:', '.join(dep)">
<span tal:condition="zone" tal:replace="thezone" />
<span tal:condition="not:zone" tal:replace="thedep" />
</tal:block>

Resources