Is it possible to get __Rendering control's template field value on content item?
Especially, I'd like to get "Data Source" field value defined in control on page item, like below screenshot.
As shown in screenshot, I have some controls in page item and I'd like to get control's "Data Source" field value.
I used this code and I could list all controls using on the page item. But, I don't know how to get the control's browsed data-source information on the page.
public RenderingReference[] GetListOfSublayouts(string itemId, Item targetItem)
{
RenderingReference[] renderings = null;
if (Sitecore.Data.ID.IsID(itemId))
{
renderings = targetItem.Visualization.GetRenderings(Sitecore.Context.Device, true);
}
return renderings;
}
public List<RenderingItem> GetListOfDataSource(RenderingReference[] renderings)
{
List<RenderingItem> ListOfDataSource = new List<RenderingItem>();
foreach (RenderingReference rendering in renderings)
{
if (!String.IsNullOrEmpty(rendering.Settings.DataSource))
{
ListOfDataSource.Add(rendering.RenderingItem);
}
}
return ListOfDataSource;
}
RenderingReference[] renderings = GetListOfSublayouts(targetItem.ID.ToString(), targetItem);
List<RenderingItem> ListOfDataSource = GetListOfDataSource(renderings);
This is exactly what I wanted.
Perfectly working!!!!!!
public IEnumerable<string> GetDatasourceValue(Item targetItem)
{
List<string> uniqueDatasourceValues = new List<string>();
Sitecore.Layouts.RenderingReference[] renderings = GetListOfSublayouts(targetItem.ID.ToString(), targetItem);
foreach (var rendering in renderings)
{
if (!uniqueDatasourceValues.Contains(rendering.Settings.DataSource))
uniqueDatasourceValues.Add(rendering.Settings.DataSource);
}
return uniqueDatasourceValues;
}
}
Here is a blog post that can help: Using the Data Source Field with Sitecore Sublayouts
Here's the relevant code you can call from within a single control:
private Item _dataSource = null;
public Item DataSource
{
get
{
if (_dataSource == null)
if(Parent is Sublayout)
_dataSource = Sitecore.Context.Database.GetItem(((Sublayout)Parent).DataSource);
return _dataSource;
}
}
Accesing the DataSource property defined above will give you the item that is assigned as the Data Source from the CMS.
Related
I have the page with placeholder and list. I want to be able to fill the list with information depending on the items in the placeholder. For example:
I have "Person" template with Name and Image Fields. I creat few items based on that template (person A, B and C). After adding the renderings with these items as a source, I display images in the placeholder. Now I want to get all the item that are currently in the placeholder and write theirs Name field into the list(which is outside placeholder).
For now I was just able to get the rendering item, but not source item, out of placeholder.
You can try bellow method:
/// <summary>
/// Return all renderings to be rendered in a specific placeholder on the "default" device
/// </summary>
private IEnumerable<Sitecore.Data.Items.RenderingItem> GetRenderings(string placeholderKey, Sitecore.Data.Items.Item item)
{
Sitecore.Layouts.RenderingReference[] renderings = GetRenderingReferences(item, "default");
foreach (var rendering in renderings)
{
if (rendering.Placeholder == placeholderKey)
{
yield return rendering.RenderingItem;
}
}
}
I was able to get source items by Id that I found in Settings of RenderingItem:
var ph = "my_placeholder";
var renderingReferences = Sitecore.Context.Item.Visualization.GetRenderings(Sitecore.Context.Device, true);
var renderingsInPlaceholder = renderingReferences.Where(r => r.Placeholder.EndsWith('/' + ph, StringComparison.OrdinalIgnoreCase));
var items = renderingsInPlaceholder.Select(x => context.GetItem(ID.Parse(x.Settings.DataSource)));
I've inherited some work on an AdminLTE sidebar on a Django website. The page in question uses an "extends" block to load AdminLTE's index.html page right off the bat. Links on our treeview sidebar cause the entire page to reload, including the sidebar, so the state of any expanded treeview menus is lost whenever someone clicks a link.
I'm guessing there's some well-known way of making the sidebar keep its treeview menus open, but I've yet to find it. There are some working examples on the AdminLTE site, but I can't figure out how they work.
Can someone point me to the right piece of documentation to help me make my sidebar persistent across page loads?
Treeview css class works in an unordered list so any child links only show up when the parent list is clicked. An example of this is if you have "home" and then "About" "About-Locations". When you click About it is a tree-view class and on the sidebar it will show locations underneath it. When you click on home the locations sidebar link will not be displayed as this is how the css is written for the list.
The code can be found in the "AdminLTE.css" file.
I'm not working on django, I work on a MVC Razor app.
For the same problem, I use this solution :
I store the link clicked on the menu (ajax send to the server and session storage, but you can use cookie or what you want).
The link clicked is inserted in the java script below :
$(" ul.treeview-menu > li > a").on("click", function ()
{
if (this.href == "#")
return;
$.ajax({
type: "POST",
url: '/Outils/SetActiveMenu',
data: { url: this.href },
dataType: "json"
});
})
$(document).ready(function () {
var v = "#Html.Raw(Session["ActiveMenu"] == null?"": Session["ActiveMenu"].ToString())";
if(v == "") return;
var a = $('a[href="' + v + '"]');
openParentMenu(a);
a.css("background-color", "#E3E6E5");
});
function openParentMenu(item)
{
var parent = item.parent().closest("li.treeview");
if (parent.length != 0) {
openParentMenu(parent);
parent[0].children.item("a").click();
}
}
Here is the code for reference.
/* Tree()
* ======
* Converts the sidebar into a multilevel
* tree view menu.
*
* #type Function
* #Usage: $.AdminLTE.tree('.sidebar')
*/
$.AdminLTE.tree = function (menu) {
var _this = this;
var animationSpeed = $.AdminLTE.options.animationSpeed;
$(menu).on('click', 'li a', function (e) {
//Get the clicked link and the next element
var $this = $(this);
var checkElement = $this.next();
//Check if the next element is a menu and is visible
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
//Close the menu
checkElement.slideUp(animationSpeed, function () {
checkElement.removeClass('menu-open');
//Fix the layout in case the sidebar stretches over the height of the window
//_this.layout.fix();
});
checkElement.parent("li").removeClass("active");
}
//If the menu is not visible
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
//Get the parent menu
var parent = $this.parents('ul').first();
//Close all open menus within the parent
var ul = parent.find('ul:visible').slideUp(animationSpeed);
//Remove the menu-open class from the parent
ul.removeClass('menu-open');
//Get the parent li
var parent_li = $this.parent("li");
//Open the target menu and add the menu-open class
checkElement.slideDown(animationSpeed, function () {
//Add the class active to the parent li
checkElement.addClass('menu-open');
parent.find('li.active').removeClass('active');
parent_li.addClass('active');
//Fix the layout in case the sidebar stretches over the height of the window
_this.layout.fix();
});
}
//if this isn't a link, prevent the page from being redirected
if (checkElement.is('.treeview-menu')) {
e.preventDefault();
}
});
};
I have used the inbuilt functionality mentioned by #MDT and have created a function:
function toggleCollapsibleList(){
//Get the clicked link and the next element
var $this = $('#parent-list-item-id');
var checkElement = $('#an-id-for-collapsible-li-with-treeview-class');
//Check if the next element is a menu and is visible
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
//Close the menu
checkElement.slideUp(500, function () {
checkElement.removeClass('menu-open');
//Fix the layout in case the sidebar stretches over the height of the window
//_this.layout.fix();
});
checkElement.parent("li").removeClass("active");
}
//If the menu is not visible
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
//Get the parent menu
var parent = $this.parents('ul').first();
//Close all open menus within the parent
var ul = parent.find('ul:visible').slideUp(500);
//Remove the menu-open class from the parent
ul.removeClass('menu-open');
//Get the parent li
var parent_li = $this.parent("li");
//Open the target menu and add the menu-open class
checkElement.slideDown(500, function () {
//Add the class active to the parent li
checkElement.addClass('menu-open');
parent.find('li.active').removeClass('active');
parent_li.addClass('active');
//Fix the layout in case the sidebar stretches over the height of the window
});
}}
This worked for me :)
How do i create a Field value for a Particular Item in a Particular Language? I have an Excel that has all the item Names inside the RootItem .These Items exist in a en-US language Already. i need add values for a particular field for other languages.. Like en-GB, nl-NL, it-IT.
I have a List like
ItemName Language Translation
TestItem en-GB Hello
TestItem nl-NL Hallo
and so on..
The only problem is, when i do item.Add, it creates a new item rather than adding the value to the existing item. How can i handle this?
My code is as follows:
foreach (DataRow row in dt.Rows)
{
Language language = Language.Parse(languageId);
var rootItem = currentDatabase.GetItem(RootItemPath, language);
var item = rootItem.Add(itemName, templateItem);
if (item != null)
{
item.Fields.ReadAll();
item.Editing.BeginEdit();
try
{
//Add values for the fields
item.Fields["Translation"].Value = strTranslationValue;
}
catch (Exception)
{
item.Editing.EndEdit();
}
}
}
Try This:
var rootItem = currentDatabase.GetItem(RootItemPath);
foreach (DataRow row in dt.Rows)
{
Language language = Language.Parse(languageId);
var itemInCurrentLanguage = rootItem.Children.Where(i=>i.Name == itemName).FirstOrDefault();
if(itemInCurrentLanguage == null){
itemInCurrentLanguage = rootItem.Add(itemName, templateItem);
}
var itemInDestinationLanguage = currentDatabase.GetItem(itemInCurrentLanguage.ID, language );
if (itemInDestinationLanguage != null)
{
itemInDestinationLanguage.Fields.ReadAll();
itemInDestinationLanguage.Editing.BeginEdit();
try
{
//Add values for the fields
itemInDestinationLanguage.Fields["Translation"].Value = strTranslationValue;
}
catch (Exception)
{
//Log any error
}
finally
{
itemInDestinationLanguage.Editing.EndEdit();
}
}
}
You need to switch the language before you get the root item:
using (new LanguageSwitcher(language))
{
var rootItem = currentDatabase.GetItem(RootItemPath);
var item = rootItem.Add(selectedItem.Name, CommunityProjectTemplateId);
// Add new item here...
}
Does anyone know how to get a list of all the items protected (and unprotected them after) in sitecore?
I've googled around but I didn't find any relevant results.
Thanks in advance
This is what I have so far...
var homeItem = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
foreach (Item item in homeItem.Children)
{
if (item.Locking.IsLocked())
{
//to do
}
}
Unfortunately the item.Locking.IsLocked is not returning if the item is protected or not.
When you press protect or unprotect item this command is called:
item:togglereadonly
This is the part of the method who protect or unprotect item:
public override void Execute(CommandContext context)
{
if (context.Items.Length != 1)
return;
Item obj = context.Items[0];
obj.Editing.BeginEdit();
obj.Appearance.ReadOnly = !obj.Appearance.ReadOnly;
obj.Editing.EndEdit();
Log.Audit((object) this, "Toggle read only: {0}, value: {1}", AuditFormatter.FormatItem(obj), MainUtil.BoolToString(obj.Appearance.ReadOnly));
}
Found the solution
var homeItem = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
foreach (Item item in homeItem.Children)
{
if (item.Appearance.ReadOnly)
{
//stuff here
}
}
Cheers
Normally, when I want to access the current Item in Sitecore, I go through Sitecore.Context.Item. This works well when creating a tool which will be used by the end user, but not for a tool which is consumed by the Sitecore admins. If I want something to show up as a custom field in the Content Editor itself, the Context.Item is a reference to the Content Editor and not to the node which is selected in the editor.
For the most part I can get around this by using the ItemID property, but if I have event dispatchers on the field, those will no longer have access to the ItemID. Eg:
protected override void OnPreRender(EventArgs e)
{
if (IsEvent)
{
// ItemID is defined here!
Button live = FindControl(GetID(LiveButton)) as Button;
if (live != null)
{
live.ServerProperties["Click"] = string.Format("{0}.LiveClicked", ID);
}
}
}
public void LiveClicked()
{
// ItemID is blank here!
DoSomething();
}
How do I gain access to ItemID in my listener (like LiveClicked above)?
The way I solved it was through something called ServerProperties and I called the equivalent to this function in every listener.
private void SyncID()
{
var live = FindControl(GetID(LiveButton)) as Button;
if (live != null)
{
if(string.IsNullOrEmpty(ItemID))
{
ItemID = live.ServerProperties["owner_id"].ToString();
}
live.ServerProperties["owner_id"] = ItemID;
}
}