GlassMapper Datasource and current item - sitecore

I am using GetDataSourceItem Method from glass mapper to return my datasource item to the view, I debug the code when the datasource is empty the calloutModel in controller will be null, but from the view, model will not be null, it will have the current item model i am using the following code :
my controller action :
public ActionResult Callout()
{
// I didn't fill the datasource in the component
// calloutModel value is coming null.
var calloutModel= GetDataSourceItem<CalloutModel>();
return View(calloutModel);
}
my view:
#inherits Glass.Mapper.Sc.Web.Mvc.GlassView<CalloutModel>
// Model is coming the current item in the view (it should be null)

It looks like this is due to the GlassView base class. That class overrides the InitHelpers method and calls its GetModel method if the model is null. The GetModel method will fall back to the context item if there is no data source item.
To prevent this, you could change your #inherits directive to an #model CalloutModel and then use the #Html.Glass() helper to get access to the Editable methods and such.

Related

Pass parameters to rendering using ItemRendering in Sitecore

I have a rendering that calls its datasources children. Each child item has a rendering attached in the renderings field.
I am calling
#Html.Sitecore().ItemRendering(item)
Which works.
However I want to pass some parameters to the child's rendering, so I tried the following code;
#Html.Sitecore().ItemRendering(item, new { Parameters = "active=1" })
But the parameters do not get passed to the child rendering when I call #Html.Sitecore().CurrentRendering.Parameters["active"]
So I tried #Html.Sitecore().ItemRendering(item, new { Active = 1 }). I called it again in the child rendering and still no luck.
Is there a way to pass parameters to the child using #Html.Sitecore().ItemRendering()
The ItemRendering method does not seem to handle properties correctly (or as one would expect!).
A work-around is to use #Html.Sitecore().Rendering() instead. You can use this in the same way as the ItemRendering method with the work-around below. Note that you should be setting the "Renderers" field of the datasource item (or its template standard values) rather than the "Renderings" field as you mentioned:
#Html.Sitecore().Rendering(item["__Renderers"], new {Datasource = item.ID, Message = "Hello World"})
In the child rendering, use the Properties property, not Parameters:
#Html.Sitecore().CurrentRendering.Properties["Message"]
var viewData = new ViewDataDictionary();
viewData["active"] = "1";
Html.Sitecore().ItemRendering(ItemToRender, viewData);
In the rendering for the Item, you can access the viewdata like this:
(ViewData["active"] != null && int.Parse(ViewData["active"].ToString()) == 1)

Sitecore, render Item in code with personalization in mvc

My terminology might be slightly off as I am new to Sitecore mvc. I am trying to hardcode a view rendering with a hard coded datasource (I have to do it this way for other requirements) This view rendering has placeholders that are dynamically set and then personalized.
How can I trigger the ViewRendering on an item?
I've tried ItemRendering, but it doesn't seem to be picking up the stuff set up in the PageEditor.
* To be clear, the helpful posts below have the rendering working, but we do not seem to be getting the personalized datasources. *
I believe this is what you're after:
Item item = /* think you already have this */;
// Setup
var rendering = new Sitecore.Mvc.Presentation.Rendering {
RenderingType = "Item",
Renderer = new Sitecore.Mvc.Presentation.ItemRenderer.ItemRenderer {
Item = item
}
};
rendering["DataSource"] = item.ID.ToString();
// Execution
var writer = new System.IO.StringWriter();
var args = new Sitecore.Mvc.Pipelines.Response.RenderRendering(rendering, writer);
Sitecore.Mvc.Pipelines.PipelineService.Get().RunPipeline("mvc.renderRendering", args);
// Your result:
var html = writer.ToString();
You can statically bind a View Rendering using the Rendering() method of the Sitecore HTML Helper. This also works for Controller Renderings using the same method.
#Html.Sitecore().Rendering("<rendering item id>")
This method accepts an anonymous object for passing in parameters, such as the Datasource and caching options.
#Html.Sitecore().Rendering("<rendering item id>", new { DataSource = "<datasource item id>", Cacheable = true, Cache_VaryByData = true })
In your view rendering, I am assuming you have a placeholder defined along with the appropriate placeholder settings in Sitecore (If not, feel free to comment with more detail and I will update my answer).
#Html.Sitecore().Placeholder("my-placeholder")
In this case, "my-placeholder" will be handled like any other placeholder, so you will be able to add and personalize components within it from the Page Editor.

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"];

addepar ember-table: how to retrieve currently selected model data

I have hooked up the content of ember-table with an ember-data model. I'm trying to get model object underlying the row that is currently selected. I've tried using this.get('selection') but to no avail. My ultimate goal is that i have an associated edit details view in a separate view that sits next to the table (aka list view) with a router (v2) that handles the transitioning between creating new models to insert into the table and edit the currently selected model (or eventually batch edit multiple models in the table). Here's the code sample:
App.TableView = Ember.Table.TablesContainer
.extend(Ember.Table.RowSelectionMixin).extend({
selectionBinding: 'controller.selection'
});
App.TableController = Ember.Table.TableController.extend({
...
selection: null,
selectionChanged: Ember.observer(function() {
this.transitionToRoute('selectedModel.edit', this.get('selection'));
}).observes('selection'),
...
I have solved this issue. What i hadn't realized is that selection is an enumerable (i'm guessing in preparation for multiple selection which would be awesome!) In the controller:
selection: null,
selectionChanged: Ember.observer(function() {
if(this.get('selection').length) {
selection0 = this.get('selection')[0];
this.transitionToRoute('selectedModel.edit', selection0);
}
}).observes('selection'),

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.