Posts tagged “umbraco”

Creating a Custom Section in Umbraco 6 - Part 2: The Tree

The tree needs a little bit more work to implement than the application.

Here is the initial class declaration.

[Tree("appAlias", "treeAlias", "Tree Title")]
public class MyApplicationTree : ITree
{
}

Tree Attribute

The Tree attribute takes similar parameters to the Application attribute.

  • appAlias - The alias of the application this tree belongs too.
  • alias - The alias for this tree.
  • title - The title of the tree, not entirely sure if this is used.

ITree

This has a few properties and methods we need to implement.

public interface ITree
{
    string app { set; }
    int id { set; }
    void Render(ref XmlDocument Tree);
    void RenderJS(ref StringBuilder Javascript);
}

The first two are easily implemented with an automatic properties.

public string app { get; set; }
public int id { get; set; }

We use the RenderJS method to add javascript to the backoffice that will allow us to change the content on the right hand side frame. We will call this when we click on a node in the tree.

public void RenderJS(ref StringBuilder javascript)
{
    javascript.Append(@"function openLocation(url) { parent.right.document.location.href = url; }");
}

Lastly we need to build our actual tree in the Render method. We need to build it in an XmlDocument and it’s fairly straightforward once you’ve done it a few times.

public void Render(ref XmlDocument tree)
{
    // Add our base elements
    XmlNode root = tree.DocumentElement;

    if (this.id == -1)
    {
        // Get data from somewhere or create a static tree root
        // Add 10 nodes for an example
        for (int i = 1; i <= 10; i ++)
        {
            XmlElement treeElement = tree.CreateElement("tree");
            treeElement.SetAttribute("menu", string.Empty);
            treeElement.SetAttribute("nodeID", i.ToString());
            treeElement.SetAttribute("text", i.ToString());
            treeElement.SetAttribute("action", string.Format("javascript:openLocation('/Path/To/Document.aspx?id={0}');", i));
            treeElement.SetAttribute("src", string.Empty);
            treeElement.SetAttribute("icon", "myClosedIcon.png"); // Icons go in ~/Umbraco/Images/Umbraco/
            treeElement.SetAttribute("openIcon", "myOpenIcon.png");
            treeElement.SetAttribute("nodeType", "tree");

            root.AppendChild(treeElement);
        }
    }
    else
    {
        // We'll come to this later.
    }
}

This should create 10 nodes in your tree, you will probably want to switch this to get data from a database or something similar. Or you may have a few static root nodes that then load data when expanded.

Child Nodes

To load child nodes in a tree, you call the tree again with the id of the parent node. This is where that if (this.id == -1) comes in. You set the tree to call in the src attribute of the node.

treeElement.SetAttribute("src", this.GetServiceUrl(i));

// ... snip ...

private string GetTreeServiceUrl(int nodeId)
{
    TreeService treeService = new TreeService(nodeId, "treeAlias", false, false, TreeDialogModes.fulllink, this.app);
    return treeService.GetServiceUrl();
}

We then catch this like so:

public void Render(ref XmlDocument tree)
{
    // Add our base elements
    XmlNode root = tree.DocumentElement;

    if (this.id == -1)
    {
        // Get data from somewhere or create a static tree root
        // Add 10 nodes for an example
        for (int i = 1; i <= 10; i ++)
        {
            XmlElement treeElement = tree.CreateElement("tree");
            treeElement.SetAttribute("menu", string.Empty);
            treeElement.SetAttribute("nodeID", i.ToString());
            treeElement.SetAttribute("text", i.ToString());
            treeElement.SetAttribute("action", string.Format("javascript:openLocation('/Path/To/Document.aspx?id={0}');", i));
            treeElement.SetAttribute("src", string.Empty);
            treeElement.SetAttribute("icon", "myClosedIcon.png"); // Icons go in ~/Umbraco/Images/Umbraco/
            treeElement.SetAttribute("openIcon", "myOpenIcon.png");
            treeElement.SetAttribute("nodeType", "tree");

            root.AppendChild(treeElement);
        }
    }
    else
    {
        // Get items that have a parent node of this.id
        // Just as an example
        XmlElement childElement = tree.CreateElement("tree");
        childElement.SetAttribute("menu", string.Empty);
        childElement.SetAttribute("nodeID", 99);
        childElement.SetAttribute("text", "Child of " + this.id.ToString());
        childElement.SetAttribute("action", string.Format("javascript:openLocation('/Path/To/AnotherDocument.aspx?id={0}');", this.id));
        childElement.SetAttribute("src", string.Empty);
        childElement.SetAttribute("icon", "icon.png");
        childElement.SetAttribute("openIcon", "icon.png");
        childElement.SetAttribute("nodeType", "tree");

        root.AppendChild(childElement);
    }
}

Need More Node Ids?

The basic tree works really well if you have a unique Id for every item and hierarchy is defined within that by parent Ids, like the content in Umbraco content. But if you need multiple roots nodes, each showing items that may have conflicting Ids, then you can add another tree.

By default all trees for an application will be added to the root, this might be what you want, but if it’s not, there is an overload for the Tree attribute to stop it being loaded.

[Tree("appAlias", "treeAlias", "My Child Tree", ".sprTreeFolder", ".sprTreeFolder_o", "", false, false)]

It’s the last boolean parameter which tells Umbraco not to initialize the tree, so it won’t be added to the root. You can then change your src attributes on your nodes to point to the new tree.

private string GetTreeServiceUrl(string treeAlias, int nodeId)
{
    TreeService treeService = new TreeService(nodeId, treeAlias, false, false, TreeDialogModes.fulllink, this.app);
    return treeService.GetServiceUrl();
}

Context Menus

You can control the context menu available on a node by setting the menu attribute on the node. This isn’t something I have implemented yet, there is more information for this available here.

Read more →

Creating a Custom Section in Umbraco 6 - Part 1: The Application

I’ve been doing a bit of work lately creating a custom section in an Umbraco v6.1 install. I needed a nice tree for my custom section, so after a lot of googling and digging through the Umbraco source, I managed to get it all working nicely. I’ve put this guide together to hopefully make the process a little easier for myself and any other weary internet travellers who happen to stumble upon it.

The Application

This is much easier now in version 6, to add a new application you just new to create a class that implements umbraco.interfaces.IApplication and has the Application attribute.

[Application("alias", "Real Name", "images/nada.gif", 10)]
public class MyApplication : IApplication
{
}

IApplication

This interface actually has no definitions, so it’s a piece of cake to implement :)

Application Attribute

This takes a few parameters:

  • alias - Your application alias, usually starts lowercase eg “myApplication”
  • name - The nice name for your application, e.g. “My Application”
  • icon - The icon to be displayed in umbraco, you’ll need to do a bit of css jiggery pokery to get it right. I’ve used nada.gif then added my icon to the existing tray sprite and added a css class which matches the application alias to position it.
  • sortOrder - You can put it at the start or in between existing apps, I set mine to 10 to make sure it was at the end.

applications.config

That should be your app set up, when you first run umbraco after creating that class, it should update the ~/config/applications.config automatically for you. I’ve found changing anything defined in the Application attribute after this point won’t be reflected in the applications.config, so if you need to make any changes, remember check that the applications.config reflects the new values.

Making it visible

When you start up Umbraco, your application should be installed but you will need to allow yourself access before it is visible. In the Users section, select your user from the Users tree and tick the box next to your new application.

Application Name

At the top of the tree on your application page, you will see that it is showing your application alias instead of the name, to update this you need to add a key setting to ~/umbraco/Config/Lang/en.xml (swapping “en” for whatever language you are using).

<area alias="sections">
    ...
    <!-- Add this line -->
    <key alias="myApplication">My Application</key>
</area>

Your app should now have a nice name.

I will post a guide to the trees later this week.

Read more →

Model.Parent == null

Thought I would put up a quick post on an issue that I came across when converting my blog to Umbraco.

I have a macro that lists posts, it will show the normal page as well as the filtered pages for categories and tags. While trying to get my tag filter to work I hit a strange issue.

if (Model.Parent != null && Model.Parent.Id == 1234)

In the above if statement, Model.Parent was always null.

Parent should only be null if you are on the homepage, so I checked Model.Level and sure enough it was 1.

It took a bit of head scratching and some fruitless googling before I realized it was because the node I was loading was called “Blog”, as was the root element of my site. Doh!

Quick rename of the tag (and the category as it would have suffered the same problem) and all was good in the world of Umbraco again.

I’m still not 100% sure on the rules of nodes with the same name. They seem to be fine if they are not direct descendants of one another.

Read more →