3

Has anybody got any examples of using the Dynatree plugin with MVC? I have been wrestling with it without much progress. I have an action method which returns a JsonResult (but selects all columns in the underlying table, not sure if this is the problem) and in my initajax call , all I'm doing is calling this method.

If it's not too much trouble, I am looking for sample View and Controller action methods.

Thanks in advance for any help

SimpleUser
  • 1,341
  • 2
  • 16
  • 36

3 Answers3

6

You need to create an object to serialize the nodes eg.

public interface ITreeItem
{
}


    /// <summary>
    /// Tree Item Leaf.
    /// </summary>
    public class TreeItemLeaf :ITreeItem
    {
        /// <summary>
        /// Gets the Title.
        /// </summary>
        public string title;

        /// <summary>
        /// Gets the Tooltip.
        /// </summary>
        public string tooltip;

        /// <summary>
        /// Gets the key.
        /// </summary>
        public string key;

        /// <summary>
        /// Gets the Data.
        /// </summary>
        public string addClass;

        /// <summary>
        /// Gets the Children.
        /// </summary>
        public IList<ITreeItem> children;

        /// <summary>
        /// Gets the rel attr.
        /// </summary>
        public string rel;

        /// <summary>
        /// Gets the State.
        /// </summary>
        public bool isFolder;

        /// <summary>
        /// Gets the State.
        /// </summary>
        public bool isLazy;

        /// <summary>
        /// Initializes a new instance of the <see cref="TreeItemLeaf"/> class.
        /// </summary>
        public TreeItemLeaf()
        {
            children = new List<ITreeItem>();
        }
    /// <summary>
    /// Initializes a new instance of the <see cref="TreeItemLeaf"/> class.
    /// </summary>
    /// <param name="type">The type of node.</param>
    /// <param name="id">The Id of the node.</param>
    /// <param name="title">The Title of the node.</param>
    /// <param name="tooltip">The Tooltip of the node.</param>
    public TreeItemLeaf(String type, Guid id, String title, String tooltip)
    {
        key = id.ToString();
        this.title = title;
        isFolder = false;
        isLazy = false;
        this.tooltip = tooltip;
        children = new List<ITreeItem>();
}

}


   /// <summary>
    /// Tree Item.
    /// </summary>
    public class TreeItem : TreeItemLeaf
    {
        /// <summary>
        /// Gets the State.
        /// </summary>
        public new bool isFolder;

        /// <summary>
        /// Initializes a new instance of the <see cref="TreeItem"/> class.
        /// </summary>
        public TreeItem() : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TreeItem"/> class.
        /// </summary>
        /// <param name="type">The type of node.</param>
        /// <param name="id">The Id of the node.</param>
        /// <param name="title">The Title of the node.</param>
        /// <param name="tooltip">The tooltip of the node.</param>
        public TreeItem(String type, Guid id, String title, String tooltip) : base(type, id, title, tooltip)
        {
            isFolder = true;
            isLazy = true;
        }

    }

Once you have this, you can return a Json(IList<ITreeItem>) which you will need to build up from your results..

If you go to the Dynatee demo http://wwwendt.de/tech/dynatree/doc/samples.html , you can use Firefox/Firebug to study the HTTP requests to see exactly what is being passed in and returned.

My tree in the view is as follows :

        // --- Initialize first Dynatree -------------------------------------------
        $("#tree").dynatree({
            fx: { height: "toggle", duration: 500 },
            selectMode: 1,
            clickFolderMode: 1,
            children : @Html.Raw(String.Format("{0}", ViewData["tree"]).Replace("\"children\":[],", "")),
            onLazyRead: function (node) {
                node.appendAjax({ 
                    url: "@Url.Action("treedata", "tree")",
                    type: "GET",
                    data: { "id": node.data.key, // Optional url arguments
                        "mode": "all"
                    },
                     error: function(node, XMLHttpRequest, textStatus, errorThrown) {

                               }
                     }
                });
            }, //.... cut short for brevity

I am embeding the initial tree state in the "children:" part. And the Ajax reading is being set up in the "onLazyRead:" part.

My Ajax call is:

    public JsonResult TreeData(FormCollection form)
    {
        return GetTreeData(Request.QueryString["id"], Request.QueryString["uitype"]);
    }

The GetTreeData() function returns Json(ITreeItem);

I would recommend you use Firefox/Firebug and its "NET" function to see what is going and coming back.

Hope that helps.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Steve
  • 2,988
  • 2
  • 30
  • 47
  • Thank you for your quick reply Steve. I'm going to create the objects as suggested and see if that will help me get a move on! – SimpleUser Sep 29 '11 at 15:25
  • The reply was quick because I am currently working on a project that uses Dynatree, its a great jQuery plugin and extremely easy to configure and use. – Steve Sep 29 '11 at 15:42
  • Steve, I'm still not having much luck here. I have defined my controller action as 'public JsonResult GetCategories()' and this is now doing a 'return Json(myTreeObj); '. I call this through the initajax call as $("#tree").dynatree({ initajax: { url: '/KBHome/GetCategories'} }); THis doesn't even hit my action for some reason! Is there a problem with my initajax call? Sorry to bother you again. – SimpleUser Sep 29 '11 at 16:08
  • Thanks for the update Steve. I just saw this, been wrestling with it non-stop now. I will try your way tomorrow. Thank you – SimpleUser Oct 03 '11 at 18:21
2

I've just found Dynatree and I'm using it on my MVC project. Here's an example of how I did it. I decided to just put the data directly in the View like the basic example.

My data is a list of cities within California, grouped by county.

My controller simply passes a view model to my View and the view model has a CitiesAvailable property:

public IEnumerable<City> CitiesAvailable { get; set; }

My list of City objects is grabbed from the database (EF4) and the actual City object is the following:

CityObject

In my View I create a ul containing the list of counties and their cities (I'm using Razor but webforms should be easy enough to figure out):

<div id="tree">
    <ul id="treedata" style="display: none;">
        @foreach (var county in Model.CitiesAvailable.Select(c => c.County).Distinct().OrderBy(c => c))
        {
            <li data="icon: 'false'">@county
                <ul>
                    @foreach (var city in Model.CitiesAvailable.Where(c => c.County == county).OrderBy(c => c.Name))
                    {
                        <li data="icon: 'false'" id="@city.Id">@city.Name</li>
                    }
                </ul>
            </li>
        }
    </ul>
</div>

Then in my JavaScript I use the following:

$("#tree").dynatree({
    checkbox: true,
    selectMode: 3,
    fx: { height: "toggle", duration: 200 }
});

It works great! Here's a sample of the output with a few items checked:

Screenshot of Dynatree result

Let me know if anything doesn't make sense.

Note, I use data="icon: 'false'" in my li elements because I don't want the icons.

Matt Penner
  • 1,082
  • 12
  • 22
  • Hey how did you late on post the data back to the server? http://stackoverflow.com/questions/9692398/dynatree-asp-net-mvc-how-do-you-post-data-back-to-server – chobo2 Mar 13 '12 at 22:27
1

You can simply convert the object to json string, and send it to server as text

this is the js code:

 var dict = $("#tree").dynatree("getTree").toDict();
 var postData = JSON.stringify(dict["children"]);
 $.ajax({ type: "POST",
                    url: "/UpdateServer/SaveUserTree",
                    data: {tree:postData},
                    dataType: "html"
                });

And this is the controller code:

 [HttpPost]
    public void SaveUserTree(string tree = "")
    {

        HttpContext.Application["UserTree"] = tree;

    }

You can send this string data back to client

   if (HttpContext.Application["UserTree"] != null)
            ViewBag.TreeData = new     HtmlString(HttpContext.Application["UserTree"].ToString());

And finally, you can initial the tree, in the View with this data:

 var treeData= @(ViewBag.TreeData)

$(function(){

    // --- Initialize sample trees
    $("#tree").dynatree({
        children: treeData
    });

});

Shabi
  • 11
  • 1