🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Turnkey treeview
This page was created by Hans.karlsen on 2017-03-20. Last edited by Wikiadmin on 2026-07-29.

You can render hierarchical ViewModel data as an expandable tree in an MDriven Turnkey application when you need a custom navigation or nested-data UI.

How the tree view works

The tree view is a custom MDriven Turnkey rendering. It replaces the generated rendering for a ViewModel column with an HTML override, then uses AngularJS directives and CSS supplied with the model.

The implementation has four connected parts:

Part Purpose Example
ViewModel structure Supplies the hierarchy and values displayed by the tree. A root collection contains root nodes; each root node contains child nodes; each node has a Label.
Content override and Angular UI override Prevent the default UI for the column and instruct Turnkey to load custom HTML. A column is configured for Content Override and has the Angular UI override value that names the override HTML file.
Override HTML Repeats over the ViewModel collections and emits nested lists with tree directives. A template repeats data.RootNodes, then each node's SubNodes.
JavaScript/TypeScript and CSS Defines the AngularJS directives that expand and collapse nodes, and styles the result. A tk-tree-node directive handles a click and hides or shows child content.

The HTML template and the ViewModel must agree on property names. The template does not need to use the names from your domain model; it uses the names exposed by the ViewModel. For example, if the template repeats data.RootNodes and then data.SubNodes, expose those names in the ViewModel even if the underlying model associations have different names.

Build the ViewModel data

Create a ViewModel that exposes a root collection and nested collections for the levels you intend to render.

For a three-level example, the data shape can be:

RootNodes
  Label
  SubNodes
    Label
    SubNodes
      Label

Each node level needs the value that the template displays. In this example, every level exposes Label.

  1. Add the root-node collection to the ViewModel.
  2. Add the node label to the root-node ViewModel class.
  3. Add a child-node collection to that class.
  4. Repeat the label and child-collection pattern for each further level that the tree supports.
  5. Populate the ViewModel with the hierarchy that you want the user to browse.

For example, a root node named Products can contain a child node named Hardware, which can contain Laptops. The template can render all three labels because each node level provides Label.

Replace the generated column rendering

Apply the custom rendering to the ViewModel column that holds the tree data.

  1. Select the relevant ViewModel column in MDriven Designer.
  2. Set the column to Content Override. This removes the normal generated rendering for that column.
  3. Set the column's Angular UI override tagged value to the name of the custom HTML override file.
  4. Create the override file with the matching name in the Turnkey override-pages location under the model assets.

In the sample, the Angular UI override names TK_treeview.cshtml. Turnkey uses that name to locate and inject the override while it renders the column. The file name configured on the ViewModel column and the file placed in the assets must match.

Create the nested HTML override

Use nested unordered lists (ul) and list items (li) to represent the hierarchy. Use AngularJS repetition to iterate the ViewModel collections, and place the tree directives on the elements that need their behavior.

The following is a structural example based on the sample's naming pattern. Adapt the number of nested levels and directive implementation to your data.

<div>
  <ul>
    <li ng-repeat="data in data.RootNodes" tk-tree-node tk-data>
      <a>{{data.Label}}</a>
      <ul>
        <li ng-repeat="child in data.SubNodes" tk-tree-node tk-data>
          <a>{{child.Label}}</a>
          <ul>
            <li ng-repeat="grandchild in child.SubNodes" tk-tree-node tk-data>
              <a>{{grandchild.Label}}</a>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

In this example, the outer ng-repeat establishes data as the current root node. Therefore Template:Data.Label displays the root-node label, and data.SubNodes identifies its children.

Keep directive names consistent

AngularJS uses different naming conventions in HTML and JavaScript/TypeScript:

In the HTML override In JavaScript or TypeScript
tk-tree-node tkTreeNode
tk-data tkData

Use hyphenated names in HTML attributes and camelCase names when registering the corresponding directive. A mismatch prevents AngularJS from recognizing the directive.

Add the directive behavior

Create a TypeScript or JavaScript file that registers the directives with the MDriven Angular application module. The tree-node directive handles the interaction for each node, such as toggling the visibility of nested child lists when the user clicks a node.

The sample also uses a data directive to add a ViewModel-class identity to rendered elements. This can help you inspect the rendered tree and identify the ViewModel item behind an element.

Keep the directive logic and its HTML attributes aligned. For example:

  • The HTML uses tk-tree-node on nodes that can expand or collapse.
  • The script registers the matching tkTreeNode directive.
  • The directive attaches the click behavior that shows or hides nested content.
  • The CSS defines the visual state of expanded and collapsed nodes.

Put assets beside the model

Store the override, compiled JavaScript, and CSS in a folder named after the model with the suffix _AssetsTK. During cloud upload, Turnkey looks for this folder and includes its contents in the upload to the Turnkey server, where the assets are expanded.

For a model named AussiWork, use:

AussiWork.eco
AussiWork_AssetsTK\
  ... JavaScript or TypeScript output ...
  ... CSS ...
  ViewsNext\
    OverridePages\
      TK_treeview.cshtml

Use the actual directory layout required by your model and Turnkey setup; the important deployment convention is the <yourModelName>_AssetsTK folder name.

When you work locally, save the model in the .eco format so that its parts are available as separate files. The video recommends this for ongoing work and source control, because the separated XML files merge more effectively in a repository than a packaged model file. A packaged model is useful when you need to share the complete model as one file.

Register the script and add CSS

Placing a script in _AssetsTK makes it available for upload; it does not by itself activate the AngularJS directives.

  1. Place the JavaScript output that contains the directive registration in the model's _AssetsTK folder.
  2. Add that script to the application's app-wide Angular script includes configuration so that Turnkey loads it.
  3. Place the tree-view CSS in _AssetsTK as well.
  4. Upload the model and assets to the Turnkey server.
  5. Open the overridden ViewModel view and verify that nodes render and expand or collapse.

If you author the directive in TypeScript, ensure that its generated JavaScript file is the file included by the application. The browser runs the JavaScript output.

Verify and troubleshoot

Use the following checks when the default UI appears, the tree is empty, or clicks do not expand nodes.

Symptom Check
The default column UI still appears Confirm that the ViewModel column has Content Override and that its Angular UI override names the correct .cshtml file.
The override does not load Confirm that the override file is in the uploaded <ModelName>_AssetsTK content and that the configured and actual file names match.
Labels or child nodes are missing Compare every template expression and ng-repeat collection with the ViewModel names. For example, the template requires RootNodes, SubNodes, and Label if those are the names it uses.
Directive behavior is absent Confirm that the script is listed in the app-wide Angular script includes configuration and that the HTML hyphenated directive name matches the camelCase registered directive name.
Styling is absent Confirm that the CSS file is in _AssetsTK and has been uploaded with the model assets.

For runtime inspection, Development info in runtime shows the definition of a selected ViewModel and the Angular widgets used to build the standard UI. The runtime debug URL can also expose live AngularJS page data, which is useful for checking whether the expected collections and labels are present.

Sample

The original sample model and its supporting files are available as File:AussiWork.7z. Inspect its _AssetsTK folder to see the tree-view override, script, and CSS together.

The accompanying tree-view walkthrough demonstrates the ViewModel hierarchy, override template, directive naming, and asset deployment convention.

See also