Template code can transform TCDL tags into the appropriate content delivery version.
Templates can output:
<tcdl:Link .../>
<tcdl:ComponentPresentation .../>
Delivery side would get tags in this format:
<tridion:ComponentLink ... />
<tridion:ComponentPresentation ... />
Question:
Is it possible to let a content author enter such a dynamic component presentation (DCP) in a rich text field format area? And if so, is a particular format preferred and how should we publish the linked-to DCP?
Edit: added context and changed link to Will's article.
Alternatively could I mimic some syntax similar to this approach from Will Price specifically for SiteEdit using DWT and C# assembly help.
I agree with John, I would implement this as a component link in the RTF. But I wouldn't use any template code, I would instead override Tridion's LinkTagHandler. In the doEndTag method, you can check if you would want to resolve the linked component as a regular dynamic link (in which case you just call the super class), or if you want to insert the DCP there (in which case you can call the ComponentPresentationTagHandler).
You can then configure your taghandler, overriding the Tridion default LinkTagHandler (you can do this in the cd_deployer_conf.xml).
Mind you, I haven't tried any of this, but I don't see why it wouldn't work.
To configure your custom tag handler, add the following to the cd_deployer_conf.xml:
<TCDLEngine>
<Properties>
<!-- keep whatever you have in this section! -->
</Properties>
<Tags>
<Tag Namespace="tcdl" Name="ContentHeader"><Handler Class="com.tridion.tcdl.tags.ContentHeaderTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="Link"><Handler Class="com.mycompany.tridion.extensions.CustomTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="Link"><Handler Class="com.tridion.tcdl.tags.DynamicLinkInfoTracker"/></Tag>
<Tag Namespace="tcdl" Name="TargetGroup"><Handler Class="com.tridion.tcdl.tags.TargetGroupTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="ComponentPresentation"><Handler Class="com.tridion.tcdl.tags.ComponentPresentationTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="FirstLine"><Handler Class="com.tridion.tcdl.tags.FirstLineTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="IncrementTrackingKey"><Handler Class="com.tridion.tcdl.tags.IncrementTrackingKeyTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="PositionMarker"><Handler Class="com.tridion.tcdl.tags.PositionMarkerTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="ContextProperty"><Handler Class="com.tridion.tcdl.tags.ContextPropertyTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="Dependency"><Handler Class="com.tridion.tcdl.tags.DependencyTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="Comment"><Handler Class="com.tridion.tcdl.tags.CommentTagHandler"/></Tag>
<Tag Namespace="tcdl" Name="TaxonomyControl"><Handler Class="com.tridion.tcdl.tags.TaxonomyTagHandler"/></Tag>
</Tags>
</TCDLEngine>
One important note: if you decide to override any of the built-in tag handlers, you need to specify all of them!
Not sure I understand fully the question but here goes:
If a user enters a component link within a rich text field depending on your configuration (type of component presentation and output type) the value will with resolved, most likely to a .
It might be worth having your own c# building block resolve to your own format, then write your own tcdl extension to parse it.
If you're trying to put Tridion component presentation inside component presentations.. I think your data model is a bit (lot!) messed up :)
Will's article refers to SiteEdit only (if I'm not mistaken). Your question is about a generic mechanism on 'including DCPs from a RTF field'.
Allowing other DCPs to be referred to from RTF is, in my view, not very kosher. I would even go as to say it is bad practice. I would avoid mixing content with layout (in the context of DCPs). I think that's something that should be done in a template or via metadata.
I think (D)CPs should be placed on a Page or queried for using some kind of metadata. I would probably prefer to have some taxonomies to tag a DCP against, then in another Component (let's call it a Control Component) you would specify some kind of criteria cocktail regarding which DCPs you want to query and display on the Page. The template will then generate some code (e.g. a custom tag) that would be executed on the Content Delivery side.
Alternatively to your request, maybe a list of links would make more sense for the authors.
Finally, to go back to your requirement, if you choose to go ahead with DCPs in RTF, then I guess it's just a matter of finding a naming convention on how to 'point' to the DCPs from RTF. One possibility would be to use a specially crafted Component Link (maybe with some specific target attribute) that a C# TBB would understand to parse out and replace with a <tridion:ComponentPresentation.../> call. I would use Component Links in an RTF because these links are maintained for integrity, consistency, porting, etc...
Related
I'm (trying) customizing the Teaser component on .content.xml to reach out to my requirements but I don't understand how I can set up an order to tabs options. The best solution would be to write some logic to hide/unhide the Teaser's fields based on the parent component, but I don't know how to do it yet. Meanwhile, I'm editing the XML file.
Options:
Image
Metadata
Text
Link & Actions
The first thing stranger is that I've written the code to show only three options but on AEM Editor keeping showing all options, with "Link & Actions" not declared on .XML. As you can see in the print below.
Path file: ui.apps/.../components/teaser/_cq_dialog/.content.xml
The second thing is that I want to put "Link & Actions" options as the last option on the tab bar. So, how make it?
The following print is my current behavior.
The behaviour you notice is due to Sling's Resource Merger feature. The same feature can be leveraged to achieve everything that you want to do.
To answer your question in parts
You see Links & Actions tab even though you've not defined it in your dialog because your component extends the OOB teaser component and the Sling Resource Merger would merge the options in the parent and the child dialogs to create the final dialog that is presented to the author.
This allows easily extending the features of the parent and only defining the custom properties within your dialog. For e.g. If you only need to add a new tab called Metadata in your teaser component it is enough to just create configurations for that new tab in your custom component and the rest of the configs will flow through from your parent component.
<tabs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs">
<items jcr:primaryType="nt:unstructured">
<metadata ...>
</items>
</tabs>
You can then use the following properties provided by Sling to further customise the ordering of the properties / tabs or remove / hide some properties.
sling:hideProperties - Specifies the property, or list of properties, to hide. The wildcard * hides all.
sling:hideResource - Indicates whether the resources should be completely hidden, including its children.
sling:hideChildren - Contains the child node, or list of child nodes, to hide. The properties of the node will be maintained. The wildcard * hides all.
sling:orderBefore - Contains the name of the sibling node that the current node should be positioned in front of.
Now to answer your second part, if you want to hide the Links & Actions tab completely in your component, then create a node called actions (same name as parent) and then set the property sling:hideResource to true
<tabs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs">
<items jcr:primaryType="nt:unstructured">
<metadata ...>
<actions
jcr:primaryType="nt:unstructured"
sling:hideResource="{Boolean}true"/>
</items>
</tabs>
Alternatively, if you don't want it removed but just moved to the end, just create a node called actions and place it after all the other nodes or use the sling:orderBefore property to specify the order of the tabs. An example of order before shown below where metadata tab appears second, followed by text and then links and actions.
<tabs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs">
<items jcr:primaryType="nt:unstructured">
<metadata
jcr:primaryType="nt:unstructured"
sling:orderBefore="text"
...>
<text
jcr:primaryType="nt:unstructured"
sling:orderBefore="actions"/>
</items>
</tabs>
EDIT: How do you know what tab names to use?:
Sling Resource Merger works when you overlay a component (think of it like inheritance in Java where you are extending another class).
You can overlay an existing component using the property sling:resourceSuperType on the component node. For e.g., this is the screenshot of my teaser component which is overlaying the OOB teaser component core/wcm/components/teaser/v1/teaser.
Since it is not an absolute path, the order of preference for seaching the component in the repository is /libs/ followed by /apps/
So, searching under /libs/ I was able to find the component at /libs/core/wcm/components/teaser/v1/teaser and expanding the dialog showed the following tabs. The same names need to be used in our component to override the position or visibility or any other sling merger features.
I would recommend understanding the inheritance concepts of Sling in general to make it easier working with AEM.
Suppose I've got comments list component with comments components. I wanna implement method that will return all comments components. I assigned to each comment component same ref:
<comments>
<comment ref="myComments" text="abc" />
<comment ref="myComments" text="efg" />
</comments>
I thought I can access all my components by this.refs.myComments but it doesn't work - it returns only last comment component.
What's the correct way to access all comment components?
There is no correct way to do that.
Your view is a representation of your data, so if you want the text for all comments, look at the data.
If you want to update the comments, update the data.
Pulling data out of the view, or manually manipulating the view defeats the purpose of react.
I'm using Alfresco Share 4.2c and I have to change a root node of an association picker. When I change some property of my document I want that picker directly points to the folder where my document is placed (parent of my document).
My problem is how to access nodeRef of document from association.ftl. I think that one solution is to use page.url.args.nodeRef, find his parent and add pass it to parameter rootNode. I'm not satisfied with that because it works only if I'm on Edit metadata page and my clients also what to use popup window to manage properties which appears on click Edit Properties link.
In that case I don't have nodeRef of document in url.
Do you have any idea how to solve this?
The best way is to a NodeLocator fur such purposes: http://docs.alfresco.com/4.1/concepts/node-locator-intro.html
the ancestor NodeLocator should be sufficient for your needs. Try the following setting in your form configuration:
<field id="my:association">
<control>
<control-param name="startLocation">{ancestor}</control-param>
</control>
</field>
How do i reorder fields that inherited from an existing behavior within a fields definition that i wrote my self.
For example I want to use the leadimage field (behavior) from plone.app.contenttypes but instead of having it at the bottom of all fields i defined, i want to have it after the description.
I've tried like this:
<property name="model_source">
<model xmlns:security="http://namespaces.plone.org/supermodel/security"
xmlns:marshal="http://namespaces.plone.org/supermodel/marshal"
xmlns:form="http://namespaces.plone.org/supermodel/form"
xmlns="http://namespaces.plone.org/supermodel/schema">
<schema>
<field name="image" type="plone.namedfile.field.NamedBlobImage" form:after="description">
<title>Image</title>
</field>
</schema>
</model>
</property>
and btw. is there a more readable way to do this?
form.order_after(image1='ILeadImage.image')
that did the trick, was a little confused within the code example...
followup question:
if i have 3 image field with each having a caption field, do i really have to add that line to every field itself? or is there a way to set the order for all fields in one place like with the fieldset definition?
I never have tried this using XML but the Dexterity XML documentation says it's possible; check the after/before attributes.
I think you can have more control using Python code; check the Form schema hints documentation.
Can anyone direct me on how to use SiteEdit specific syntax or tags in the Razor template in DD4T code? I have seen Site Edit related classes in it, but could not understand how to use SiteEdit tags in the view where there were some syntax similar to Dreamweaver for example RenderComponentField or tcdl:ComponentField which we used in Dreamweaver. I am very new to DD4T and am using SiteEdit 2009 SP3 and SDL Tridon 2011 SP1.
Thanks in advance.
Update: We have tried the implementation mentioned in the answer but unfortunately we are getting an error when we are accessing the page in proxy stating "Invalid template -The HTML is invalid, probably because your template code produces invalid HTML, such as a p tag inside another p tag. Check your HTML using a validator such as the W3C Markup Validation Service, correct your template, and republish."
I guess this is because Xml content is being pushed into html page due to the use of Dynamic Page and Component TBBs which we used in our Component and Page Templates.
Let us kow how to continue further.
The SiteEdit markup is not generated like it is done in a Dreamweaver Template, you are responsible yourself to place the markup for your editable fields in the Razor view. Good thing for this is that it works for similar for SiteEdit 2009 SP3 and UI 2012. Downside for UI 2012 is that it is not listening (yet) to the Enable Inline Editing which you can set on the Component or Page Templates (something we should consider for a future DD4T version).
Everything is based on the DD4T SiteEditHelper class. You start in your page view (before the </body> tag) by placing the following call:
#Html.SiteEditPage(Model)
This will write out the page markup, and if you set the style to "SiteEdit2012" in your SiteEdit_config.xml it will also write out the bootstrap script required for UI 2012.
Then for every Component Presentation and every editable Component Field you will also need to add the appropriate markup. For a Component presentation you can use:
#{var ComponentPresentation = ViewBag.ComponentPresentation as IComponentPresentation;}
<div>
#Html.SiteEditComponentPresentation(ComponentPresentation)
</div>
Make sure you write this out inside a DIV or some other element that can mark the boundary of your Component Presentation. For Component Fields a similar story, you can use:
<div>
#Html.SiteEditField(Model, Model.Fields["FieldName"])
#Model.Fields["FieldName"].Value
</div>
Apart from the changes to your views, as Bart has described, you also need to put a configuration file in the root of your web application, called SiteEdit_config.xml. It should look like this:
<?xml version="1.0" encoding="utf-8" ?>
<siteEdit enabled="true" tridionHostUrl="http://tridion.my.com">
<contextPublications>
<contextPublication id="10" componentPublication="3" pagePublication="9" publishPublication="10" />
<contextPublication id="11" componentPublication="3" pagePublication="9" publishPublication="11" />
</contextPublications>
</siteEdit>
You must list all your active publications here. DD4T tries to match your current page to the correct context publication (based on the 'id' attribute). If it cannot find it, SiteEdit will be disabled. The other attributes allow you to control the behaviour of SiteEdit.
componentPublication: new components will be created here
pagePublication: new pages will be created here (not used in Tridion UI 2012)
publishPublication: pages and components will be republished from this context (usually coincides with the id)
DD4T can also easily be configured for use with Tridion UI 2012. Just change the first element in the configuration as follows:
<?xml version="1.0" encoding="utf-8" ?>
<siteEdit enabled="true" style="SiteEdit2012" tridionHostUrl="http://tridion.my.com">
...
</siteEdit>