Monday, September 22, 2014

Example of Sitecore Command Template With User Interface

Command template define a class and method to be called during an insert operation. Unlike data templates and branch templates, which consist of predefined structures, command templates reference Sitecore UI commands to invoke wizards or other logic used to create new items.


We can create a command template that displays no user interface, a command template that uses a JavaScript prompt to collect an item name, or a command template that displays an ASP.NET or Sitecore Sheer user interface.

We can assign command templates along with data templates and branch templates using insert options.
Following example demonstrates creation of a command template which would check if a folder with current year name exists under main item “News”  and add a “News Item” in that folder. This example uses a JavaScript prompt to collect News Item name.

Step 1: Create two templates “News” & “News Item” with required fields.

Step 2: Create a class that inherits from Sitecore.Shell.Framework.Commands.Command, and override the Execute() method.

namespace Demo.Commands
{
    public class NewsItemCommand : Sitecore.Shell.Framework.Commands.Command
    {
        public override void Execute(Sitecore.Shell.Framework.Commands.CommandContext context)
        {
        }
    }
}

Step 3: Add a /configuration/command element to the file /App_Config/Commands.config.





Step 4: Under the appropriate project-specific folder within /sitecore/Templates, insert a command template definition item using /System/Branches/Command Template data template.






















Step 5: In the command template definition item, in the Data section, for the Command field, enter the command code.


















The parameter id=$ParentID passes the ID of the item under which the user is inserting a new item. Without this parameter, Sitecore would pass the ID of the selected item rather than the item the user right-clicked.

Step 6: Assign this command template to standard values of the “News” template created in step1.




















Step 7: Create a new aspx page in “/sitecore modules/shell”










Step 8: Complete required code in the command class.

public override void Execute(Sitecore.Shell.Framework.Commands.CommandContext context)
        {
            if (context.Items != null && context.Items.Length > 0)
            {
                Item contextItem = context.Items[0];
                NameValueCollection parameters = new NameValueCollection();
                parameters["id"] = contextItem.ID.ToString();
                parameters["name"] = contextItem.Name;
                parameters["database"] = contextItem.Database.Name;
                parameters["language"] = contextItem.Language.ToString();
                Sitecore.Context.ClientPage.Start(this,"Run", parameters);//Run method executes on

            }
        }
        protected void Run(Sitecore.Web.UI.Sheer.ClientPipelineArgs args)
        {
            if (args.IsPostBack)
            {
                if (!(String.IsNullOrEmpty(args.Result)) && (args.Result != "undefined") && (args.Result != "null"))
                {
                }
            }
            else
            {
                Sitecore.Text.UrlString url = new Sitecore.Text.UrlString("/sitecore modules/shell/Demo/News.aspx");
                url.Append("id", args.Parameters["id"]);
                url.Append("database", args.Parameters["database"]);
                Sitecore.Context.ClientPage.ClientResponse.ShowModalDialog(url.ToString(), true);
                args.WaitForPostBack(true);
            }
        }   

Step 9: Handle “OK” and “Cancel” buttons of the user interface News.aspx

protected void btnOK_Click(object sender, EventArgs e)
        {
            if (! String.IsNullOrEmpty(txtNewsItem.Text))
            {
                Sitecore.Data.Database currentDatabase = Sitecore.Configuration.Factory.GetDatabase(Sitecore.Web.WebUtil.GetQueryString("database"));
                Item parentItem = currentDatabase.GetItem(Sitecore.Web.WebUtil.GetQueryString("id"));
                if (parentItem != null)
                {
                    //check if News item contains a folder with current year
                    Item[] children = parentItem.Axes.GetDescendants();
                    Item currentYearItem = children.Where(x => x.TemplateName == "Folder" && x.Name == DateTime.Now.Year.ToString()).SingleOrDefault();
                    if (currentYearItem == null)
                    {
                        Sitecore.Data.Items.TemplateItem folderTemplate = currentDatabase.GetTemplate(Sitecore.TemplateIDs.Folder);
                        if (folderTemplate != null)
                        {
                            Item i = parentItem.Add(DateTime.Now.Year.ToString(), folderTemplate);
                            currentYearItem = i;
                        }
                    }
                    //create a news item and add it to the current folder
                    Sitecore.Data.Items.TemplateItem newsItemTemplate = currentDatabase.GetTemplate(new Sitecore.Data.ID("{D8BE36D8-20F0-4BCF-856C-D069E845D136}"));
                    Item newsItem = currentYearItem.Add(txtNewsItem.Text, newsItemTemplate);
                    ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Close", "window.top.dialogClose();", true);
                }
            }
            else
            {
                ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Warning", "alert('Please enter news item');", true);
            }
        }
        protected void btnCancel_Click(object sender, EventArgs e)
        {
            ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Close", "window.top.dialogClose();", true);
        }

Step 10: Create a main news item based on “News” template.

Step 11: Create a news item under main item by clicking the command template which would create a folder with current year and a “News Item” under that folder.











































4 comments:

  1. Great post. Thanks for sharing :)

    ReplyDelete
  2. wow amazing post.. Thanks for info

    ReplyDelete
  3. Great post, thanks for sharing. I have one problem as my situation is a little different.

    My situation requires the user to input a few things in the aspx page and then I take that info, create a new item, and move it to a specific folder.

    My question is: After I move the newly created item to the folder I need to move it to, how can I refresh the new folder item and focus on the new item I created?

    My problem is that when I create the item, I do not see it right away. I am forced to manually refresh the folder in order to see the new item.

    Let me explain in more detail:

    Content Tree:
    Publications
    |
    |
    ----Folder 1
    |
    |
    ----Folder 2

    I created my command template and assigned the insert options to my "Publications" item. This works!!! I then create the item via the aspx code behind, perform some logic to determine which folder it needs to go into and then move. This also works!!!

    Now, lets say I moved the new item to "Folder 1". In sitecore, once the item is created and moved, I do not see the new item until I refresh the folder.

    I tried using the following code in the code behind to refresh the folder but it doesn't work:

    // Get the context Item
    Item created = Client.GetItemNotNull(ID.Parse(args.Parameters["id"]));

    // Sending these messages result in refreshing the child items of the Context item
    Sitecore.Context.ClientPage.SendMessage(this, string.Format("item:updated(id={0})", newItem.ID));
    Sitecore.Context.ClientPage.SendMessage(this, string.Format("item:refreshchildren(id={0})", newItem.ID));

    Now, if I put this same code in the command template cs file, it will work but the only problem is that I am unable to get the ID of the newly created item. The only ID I can access it the context item which in this case is the Publications Folder Item.

    So, how can I work around this? Is there a way to pass the ID of the newly created item as part of the postback? Or is there a way to refresh the item in the code behind file?

    Hopefully someone can help as I am stuck at this point.

    Thanks!!!

    ReplyDelete