Copy Presentation Details to new PlaceHolder programmatically Sitecore 7.2 - sitecore

currently I am working on a page that generates a print view of a specific item. So this means I dont need all the stuff from my MainLayout like Navigation etc.
For this reason I have created a new Layout that only has a placeholder.
Lets call this PrintLayout.aspx:
<sc:placeholder ID="PlPrint" runat="server" key="phPrintOutput"></sc:placeholder>
In the code behind I have a method that fetches the renderings from the item, but I am stuck at the point where I want to copy them to my phPrintOutput Placeholder on the fly:
public void AddPresentationDetailsToPlaceHolder(Item item)
{
List<RenderingReference> renderings = item.Visualization.GetRenderings(Sitecore.Context.Device, false).ToList();
foreach(RenderingReference r in renderings)
{
// How can I apply the renderings on the fly to my phPrintOutput Placeholder??
}
}
Of course it is very important that every sublayout keeps it current datasource.
Any help would be appreciated, thank you all

You only require to add the control to the placeholder. To do so, please see the code below:
public void AddPresentationDetailsToPlaceHolder(Item item)
{
List<RenderingReference> renderings = item.Visualization.GetRenderings(Sitecore.Context.Device, false).ToList();
foreach(RenderingReference r in renderings)
{
if(r.RenderingID == new ID("Rendering Id you want to be displayed on layout"))
{
this.PlPrint.Controls.Add(r.GetControl());
}
}
}
This will automatically add the rendering to the layout.

Related

Sitecore 8: Automatically fill a placeholder by a default rendering

I was playing around with dynamic placeholders and was struck by a prefilling concept.Is there a way to select a default rendering for one of my placeholders which would avoid the "select rendering" dialog in experience editor ??
Scenario: I have a rendeing called "PageHead" which has three renderings. One of them is a placeholder "PageTeaserPh" which currently allows two renderings: one is "PageTeaser" and second "PageTeaserWithImage". I want the placeholder "PageTeaserPh" to always have the rendering selected as "PageTeaser" and therefore avoid the dialog "Select rendering" .
I did some homework and was wondering if this is something related to Standard values (we can have it at template level; not sure for renderings though) and also i have heard of command template concept (not in-depth).
Any and all help appreciated.
You can have renderings assigned on standard values of templates, each new item would then have your PageTeaser rendering.
If you wanted to automate this process have a look at the <mvc.getXmlBasedLayoutDefinition> pipeline, we are injected common renderings by extending this pipeline.
Updated
I've found some code samples and blog posts that should help point you in the right direction for manipulating the layout details.
public void AddSublayoutToItem(string itemId, string sublayoutId)
{
using (new Sitecore.SecurityModel.SecurityDisabler())
{
if (Sitecore.Data.ID.IsID(itemId) && Sitecore.Data.ID.IsID(sublayoutId))
{
//Get the master database and get the item on which you want to add sublayout
Database masterDatabase = Database.GetDatabase("master");
Item item = masterDatabase.GetItem(Sitecore.Data.ID.Parse(itemId));
// Or you can also get Sitecore Item from Context Database as per your requirement
// Item item = Sitecore.Context.Database.GetItem(Sitecore.Data.ID.Parse(itemId));
if (item != null)
{
// Get the layout definitions and the device definition
LayoutField layoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.LayoutField]);
LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);
DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(Sitecore.Context.Device.ID.ToString());
//Create a RenderingDefinition and add the reference of sublayout or rendering
RenderingDefinition renderingDefinition = new RenderingDefinition();
renderingDefinition.ItemID = sublayoutId;
//Set placeholder where the rendering should be displayed
renderingDefinition.Placeholder = "content";
// Set the datasource of sublayout, if any
renderingDefinition.Datasource = "{24240FF2-B4AA-4EB2-B0A4-63E027934C38}";
// you can also set datasource of sublayout using Sitecore Path
// renderingDefinition.Datasource = "/sitecore/content/Home/Books";
//Add the RenderingReference to the DeviceDefinition
deviceDefinition.AddRendering(renderingDefinition);
// Save the layout changes
item.Editing.BeginEdit();
layoutField.Value = layoutDefinition.ToXml(); ;
item.Editing.EndEdit();
}
}
}
}
Taken from here - http://www.bugdebugzone.com/2014/06/how-to-add-sublayout-to-sitecore-item.html
Also a couple of other blogs on the topic

data-dialog created dynamically

I'm using polymer 1.0.
I'm trying to open a with on a clic on an element created dynamically with template repeat.
Here is the code :
<paper-button
data-dialog="modal"
on-click="dialogClick">
Click
</paper-button>
and the script (from doc) :
dialogClick: function(e) {
var button = e.target;
while (!button.hasAttribute('data-dialog') && button !== document.body) {
button = button.parentElement;
}
if (!button.hasAttribute('data-dialog')) {
return;
}
var id = button.getAttribute('data-dialog');
var dialog = document.getElementById(id);
alert(dialog);
if (dialog) {
dialog.open();
}
}
This work only if the value of data-dialog is simple text. If I want to change it by data-dialog="{{item.dialogName}}" for instance, it doesn't work. It is not found by the while loop and exit with the if. in the source code of the page, there is no data-dialog in the paper-button.
Any idea ?
I've ran into a similar problem when using data attributes on custom elements. You might want to subscribe to this polymer issue.
As a workaround, place the data attribute in a standard element that is a parent of the button and search for that one instead.
Also, you might want to consider using var button = Polymer.dom(e).localTarget instead of directly accessing e.target, since the later will give you an element deeper in the dom tree under shady dom.

Issue trying to use Datasource Template in Sitecore sublayout; getting empty Sublayout.Datasource

We've been trying to "componentize" our Sitecore solution as we move forward, in prep for transitioning to Page Editor usage (Woot! Finally!), but we're still practically working primarily with Page templates that may be inheritance-based composites of page specific fields, plus 1:many of these componentized templates. An example of how this looks in our solution is below -- Banner Feature Carousel and Featured Cartoon are some of these new components we're creating:
In the interest of trying to move away from using Sitecore.Context.Item (as I was recently reminded by this post) I've started filling in the Datasource template field on the sublayouts for the new components, and it seems like I've got the appropriate connections made between presentation details, the Sitecore sublayout and the .NET code file (as far as I can tell; again, we're newer to working this way).
I've also tried setting up a base class for these components as per this post by Nick Allen, but here's where I'm running into a problem: When I execute my code, this base class is finding the component Sublayout appropriately (the whole "this.Parent as Sublayout" thing) but, when I go to interrogate the Sublayout.Datasource property, it's an empty string. Here's my code (so far) for this base class:
public class ComponentBase : System.Web.UI.UserControl
{
private Sublayout Sublayout { get { return Parent as Sublayout; } }
public Item DataSourceItem
{
get
{
return Sublayout != null && !String.IsNullOrEmpty(Sublayout.DataSource) ?
Sitecore.Context.Database.GetItem(Sublayout.DataSource) : Sitecore.Context.Item;
}
}
}
I'm apparently missing some interplay between the Datasource Template field in the Sitecore sublayout, and how that actually translates to a datasource. Is it because these component templates are being used to compose Page templates? I was thinking that the datasource would just ultimately resolve to the Page template on which the component in question was currently being used, but perhaps that's my misunderstanding.
If anyone could give me any hints of things to check or point me to any resources I might use to get further, I'd appreciate it. I've done quite a bit of asking the Googs, myself, but am just not getting anything that's helping.
Thank you in advance, Sitecore friends!
It looks like you have configured the allowed templates for your sublayout in the steps you describe above. This basically tells Sitecore; 'allow user to select items based on these templates for this sublayout'. This alone does not set up the data source on items using the sublayout. You still need to go into the presentation details for any items using this sublayout, select the sublayout and then set its datasource property (within the content editor go to Presentation > Details > [Sublayout] > Data Source).
My answer to this question gives the source code needed to retrieve the datasource item and to iterate through the sitecore controls on your sublayout setting all of their Item propertys.
Here is the code:
public class SublayoutBase : UserControl
{
private Item _dataSource;
public Item DataSource
{
get
{
if (_dataSource == null)
{
if (Parent is Sublayout)
{
_dataSource =
Sitecore.Context.Database.GetItem(((Sublayout)Parent).DataSource);
}
if (_dataSource == null)
{
_dataSource = Sitecore.Context.Item;
}
}
return _dataSource;
}
}
protected override void OnLoad(EventArgs e)
{
foreach (Control c in Controls)
{
SetFieldRenderers(DataSource, c);
}
base.OnLoad(e);
}
private void SetFieldRenderers(Item item, Control control)
{
if (item != null)
{
var ctrl = control as Sitecore.Web.UI.WebControl;
if (ctrl != null && !string.IsNullOrEmpty(ctrl.DataSource))
{
//don't set the source item if the DataSource has already been set.
return;
}
if (control is FieldRenderer)
{
var fr = (FieldRenderer)control;
fr.Item = item;
}
else if (control is Image)
{
var img = (Image)control;
img.Item = item;
}
else if (control is Link)
{
var link = (Link)control;
link.Item = item;
}
else if (control is Text)
{
var text = (Text)control;
text.Item = item;
}
else
{
foreach (Control childControl in control.Controls)
{
SetFieldRenderers(item, childControl);
}
}
}
}
}
When you start using sublayouts on which you will set your datasource try to use the marketplace "Sublayout Parameter Helper". When you use the class they provide as base class and have set everything up right in your Sitecore Environment you will find yourself having a "this.DatasourceItem" -> which will contain your datasource Item, or the context Item if none is given.
http://marketplace.sitecore.net/en/Modules/Sub_Layout_Parameter_Helper.aspx
To find out more on how datasource works, try searching on http://sdn.sitecore.net. There is alot of documentation available that should get you in the right direction. Generally it will be enough to just add a datasource in the sublayout that you can access in your sublayout.
When you read a datasource from a sublayout all it will do is check if the datasource field on that sublayout is filled and will return you information regarding this datasource. So when you add a new component to a page using the page editor (for example a sublayout for a news article) and you have a datasource template defined and filled in during adding this components, you will see that when you check the presentation details on that page a sublyaout with a datasource has been added. The datasource will point to a folder in which you will find an item based on the datasource template you specified on your sublayout. You should also double check this, cause if no datasource is present on the added sublayout it will be obvious you can't access it from your code.
If you are using Sitecore 7 update 1 you can actually now use the attributes. From the Release Notes:
To make it easier to get the data source for a sublayout from
code-behind, the data source is now transferred to the sublayout
control in a "sc_datasource" attribute. (320768)
To get the data source from code, simply refer to
this.Attributes["sc_datasource"];

How to render referenced items from current item in Sitecore?

Let say I have item which has its presentation details configured.
In that item I have TreelistEx field keeping reference (GUIDs) to 10+ other items (different templates) somewhere in the tree structure each of them has their own presentation details (sublayouts).
How can I present all reference items on the same page ( as current item) based on their own settings?
I would like to see one page and 10+ pieces of content each with its own layout presentation.
I had a similar problem. Here is the code for rendering sublayouts and xsl renderings:
public IEnumerable<Control> GetRenderingControls(Item item)
{
// Loop through all renderings on the item
foreach (RenderingReference rendering in item.Visualization.GetRenderings(Context.Device, false))
{
// Get the path to the Sublayout
string path = rendering.RenderingItem.InnerItem["Path"];
switch(rendering.RenderingItem.InnerItem.TemplateName.ToLower())
{
case "xsl rendering":
// Create an instance of a XSL
XslFile xslFile = new XslFile();
xslFile.Path = path;
xslFile.DataSource = item.Paths.FullPath;
xslFile.Parameters = GetParameters(xslFile);
yield return xslFile;
break;
case "sublayout":
// Create an instance of a sublayout
Sublayout sublayout = new Sublayout();
sublayout.Path = path;
sublayout.DataSource = item.Paths.FullPath;
sublayout.Parameters = GetParameters(sublayout);
yield return sublayout.GetUserControl();
break;
default:
throw new Exception(string.Format("Unknown rendering template - {0}", rendering.RenderingItem.InnerItem.TemplateName));
}
}
}
Once you get the Controls you can add them to a placeholder and they will be rendered to the page.
Each item with its own layout presentation implies you are getting an entire HTML file... each item will have its own <html>, <head>, and <form> tags. Needless to say, that's going to create a problem.
That being said... This is exactly what Server.Execute() is for. Loop through your TreeList items, use LinkManager to get the URL for the item, and then Server.Execute() to get the rendered output.

Sitecore rule does not set the data source to other item?

This is my rule
where user profile fb_likes field contains sitecore
set data source to TestItem2
I have applied this rule to a sublayout on standard values of the template,but this rule never change the data source.
I have also tried this condition
where true (action always execute).
but again no luck,
if I change action to
hide rendering
it works fine.
what I'm doing wrong here??
Does the code of your sublayout make allowances for using the Datasource when it is set over the context item? You can achieve this in a number of ways. E.g in a base class:
protected string DataSource
{
get
{
var sublayout = Parent as SublayoutBase;
return sublayout == null ? string.Empty : sublayout.DataSource;
}
}
protected Item DataSourceItem
{
get
{
return string.IsNullOrEmpty(DataSource)
? Sitecore.Context.Item
: Sitecore.Context.Database.GetItem(DataSource) ?? Sitecore.Context.Item;
}
}
Then inside your code for your sublayout use the DatSourceItem rather then the context item to display content. Another way I have seen this done is to:
protected override void Render(HtmlTextWriter writer)
{
if (this.DataSourceItem != null)
using (new Sitecore.Data.Items.ContextItemSwitcher(this.DataSourceItem ))
{
base.Render(writer);
}
else
{
base.Render(writer);
}
}
Using this all your sublayouts that inherit this in their base class will natively support Data source even if the code is written against the Context item.