What does CQ5's Placeholder.getDefaultPlaceholder exactly do? - aem

The API docs are not much descriptive:
Get default placeholder for any component incl. title as text information
Here's the method signature:
public static String getDefaultPlaceholder(ServletRequest slingRequest,
Component component,
String defaultPlaceholder)
What's a Placeholder? What is/should be returned by getDefaultPlaceholder?
What's the purpose of defaultPlaceholder? What should I pass as defaultPlaceholder? What would happen if I pass null?

When a component does not have any content defined you need to put a placeholder to occupy its place (for the editor to know there's a component there).
The getDefaultComponent returns a HTML snippet that works as the placeholder. It consists of an empty div with attributes class and data-emptytext with the title of the component as its value.
<div class="" data-emptyText="component.getTitle()"></div>
You can also pass an additional parameter with a list of strings and they will be added in the class attribute of the div.
getDefaultPlaceholder(ServletRequest slingRequest,
Component component,
String defaultPlaceholder,
String... addClasses)

Related

Cannot programmatically add content to simple HTML DIV Element in XML view

I have a simple XML view (fragment) like this:
<html:div id="holder"></html:div>
I want to add content programmatically like this:
var holder = this.byId("holder");
var label = new sap.m.Label({
text: "Label"
});
holder.addContent(label);
Effect is nothing, no error, no added content.
Why does it not work?
This is because content is not an aggregation (an easy mistake to make, since content usually is an aggregation).
sap.ui.core.HTML's content metadata object is a property of type string. From the jsdoc:
HTML content to be displayed, defined as a string.
You will need to use a different container for your label, such as sap.ui.layout.VerticalLayout, or you could just use raw HTML to stick in your holder object, rather than that sap.m.Label type.
Here is a jsbin that takes the XML view part of this question out of the equation.
Note: See #hirse's comment below for an important distinction when using html:div in XML views
The HTML element and the UI5 Controls are not directly compatible. UI5 Controls are JavaScript objects that have a render function. The render function creates a html fragment on demand. That html fragment ist then inserted into the page.
I have never tried it, but a solution could be to use the placeAt() method of your label:
label.placeAt("holder");
If you are using an XML View, the holder id will be prefixed. Then you should use something like this:
label.placeAt(this.getView().createId("holder"));
You can get DOM element of UI5 control by using getDomRef of sap.ui.core.Element class.
Then add your content to this DOM element by using placeAt()
Here is working example.

Given a Path get a reference to the Resource in Sightly

The component dialog has a pathfield widget where the authors can set a page path. In the Sightly component, I would like to look up that page resource and get (and display) properties from it.
The dialog...
<linkedPathLocation jcr:primaryType="cq:Widget"
fieldLabel="Linked Path"
name="./linkedPathLocation"
xtype="pathfield"
fieldDescription="Select a page. URL, Title, Description and Image are properties of the selected page"/>
The component code I would like to work (it's not).
<div class="row" data-sly-resource.page = "${properties.linkedPathLocation}">
<h1 >${page.title}</h1>
<p>${page.description}</p>
</div>
My question: Is there a way in Sightly to resolve and use some resource from a given path? If not, I could create a USE-API class and to do the following...
Page page = resourceResolver.resolve("/path/to/resource").adaptTo(Page.class);
I feel there should be a better answer which allows resources to be resolved directly from the Sightly, but the following USE-API solution works if not...
Java Use Class
public class PageHelper extends WCMUsePojo {
String pagePath = "";
#Override
public void activate() {
pagePath = get("path", String.class);
}
public Page getPage() {
return this.getPageManager().getPage(pagePath);
}
}
The component Sightly...
<div class="row" data-sly-use.linkedPage = "${'com.package.PageHelper' # path = properties.linkedPathLocation}">
<h1 >${linkedPage.page.title}</h1>
<p>${linkedPage.page.description}</p>
</div>
What you are trying to do, in essence, is render a Resource within the context of the rendering of another Resource. data-sly-resource seems the appropriate attribute to use, but instead of attempting to nest additional elements into the element containing the data-sly-resource you should define another Sightly .html file which dictates how the nested resource is to be rendered.
Let us say that your Resource is of type application/components/content/type. Within type.html you might have the following statement
<sly data-sly-resource="${properties.linkedPathLocation} # resourceType='application/components/content/type/subtype' />
You would then be able to define /apps/application/components/content/type/subtype/subtype.html containing the rendering to produce which would be invoked in the context of the Resource identified by your path.
The main purpose of Sightly templates is separation of responsibility (frontend & backend) so that we can have simple, clean and beautiful html markup which is designer friendly and easily readable.
For your case, writing a Class (Java/Javascript) to process dialog information, and supply it back to Sightly template is correct way. Read here for more details.

Is wicket:label needed with wicket:for?

In the past I have built labels for my form like this:
<label wicket:for="name"><wicket:label><wicket:message key="name"></wicket:message></wicket:label>:</label><input wicket:id="name" type="text"/>
Do I still need to use the wicket:label tag? I am not using wicket:label in wicket 7 and it seems to work fine. I may not be understanding the purpose of using wicket:label. It seems like wicket:label is just additional markup. Below is what I am doing now. Is this correct?:
<label wicket:for="name"><wicket:message key="name"></wicket:message>:</label><input wicket:id="name" type="text"/>
This example is related to Wicket XHTML tags
Have a look at the JavaDoc of AutoLabelResolver and AutoLabelTextResolver.
The <label wicket:for="name"> is handled by AutoLabelResolver. It links the HTML label tag to the HTML form component (in your case the input tag) by filling in the correct ID in the HTML for attribute of the label. It also adds css classes to the label tag for for example errors, so you can style the text in the label tag in case of an error.
The <wicket:label> has two purposes. If you give it a value either by the key attribute (as you did) or by having some text between the tags, the text is set as the label model of the Java FormComponent, which then is used in validation messages like this '${label}' is required. (see LabeledWebMarkupContainer#setLabel and LabeledWebMarkupContainer#getLabel).
If you don't assign any text to the <wicket:label> tag, then it is used as output. That means the value of the label model of your Java FormComponent is used to replace the tag.
If you have no <wicket:label> in the HTML markup and no label model set in your Java code, then your Java FormComponent will have an empty label model and Wicket falls back to using the Wicket ID as label. So depending on how your Wicket IDs look, you will get validator messages like 'user_name' is required. instead of something nice looking like 'User name' is required.

Wicket - can you specify markups IDs for elements inside repeaters?

I'm having a hard time testing our Wicket application using Selenium because of the random markup ids.
For individual elements, I can use abc.setOutputMarkupId(true).setMarkupId("myId")
to set their markup id explicitly.
But what if the element is added dynamically using a repeater (like ListView)? Is there a way to specify how the markup id sequence should look like?
Well, can't you do the same thing with ListView? If you make your own ListView implementation, and then in the populateItem(final ListItem<?> listItem) method, on that respective listItem you do:
listItem.setOutputMarkupId(true); // write id attribute of element to html
listItem.setMarkupId("id"+i);
where i is some index you initialize in the ListView's constructor or something?
as Andrei told that its possible but dangerous.
setMarkupId doc:
Retrieves id by which this component is represented within the markup. This is either the id attribute set explicitly via a call to
org.apache.wicket.Component.setMarkupId(java.lang.String), id
attribute defined in the markup, or an automatically generated id - in
that order. If no explicit id is set this function will generate an id
value that will be unique in the page. This is the preferred way as
there is no chance of id collision.
http://www.kiwidoc.com/java/l/p/org.apache.wicket/wicket/1.4.0/p/org.apache.wicket/c/Component#top
and also you cant get the markup id with getMarkupId()

How to use Razor like asp:Literal?

I have a simple Model:
public class MyModel
{
public string Text{get;set;}
}
I have a View, which renders Text property of MyModel:
<p>#Model.Text</p>
How can I render html tags from Text like tags? For example, I have Text "<b>Text</b>". I want to get bold text inside tag p as result:
Text
But Razor renders text as is:
<b>Text</b>
I think you need to use it like:
<p>#Html.Raw(Model.Text)</p>
You can find more info here on Phil Haack's blog.
anurse points out in the comments that you could, alternatively, set the type of the Text member of your View Model type as IHtmlString and just use #Model.Text to output it. ASP.NET MVC is clever enough to realize that the output should not be escaped.