Edit this page

ng-* Directives in Widget Markup

Prior to the Kendo UI Q2 2015 release, the widgets which were instantiated over existing markup partially supported ng-repeat, ng-if, ng-bind, and other DOM manipulation directives in the markup.

However, subsequent changes to the markup, caused by those directives, were not handled correctly.

Overview

The widgets which exhibited this behavior were the TabStrip, PanelBar, Menu, TreeView, and some of the hybrid mobile widgets. This behavior was accidental and was caused by the directives instantiating the widgets in a $timeout (setTimeout) wrap.

The timeout initialization caused several other issues as well. The widget instances were not accessible in a reliable manner. The instantiation of each widget required several additional $scope.digest cycles to be executed. Performance was negatively affected and the widget initialization was visible to the end user in certain scenarios. The change from June 17 2015 removed the timeout implementation, effectively breaking the accidental ng-repeat support in later releases.

Approaches

The dataSource Option

The recommended approach to achieve dynamic content generation for the listed widgets is through the dataSource configuration option.

The following example demonstrates a Kendo UI TreeView widget with DataSource in AngularJS.

Example
<div ng-app="app" ng-controller="MyCtrl">
    <button ng-click="add()">Add new</button>
    <div kendo-tree-view k-data-source="tree"></div>
</div>
<script>
angular.module("app", ["kendo.directives"]).controller("MyCtrl", function($scope) {
    $scope.tree = new kendo.data.ObservableArray([
      { text: "Foo", items: [
        { text: "Foo 1" },
        { text: "Foo 2" } ] },
      { text: "Bar", items: [
        { text: "Bar 1" },
        { text: "Bar 2" } ] },
    ]);
    $scope.add = function() {
      $scope.tree.push({
        text: "This works",
        items: [ { text: "Sweet" } ]
      });
    };
});
</script>

The following example demonstrates a Kendo UI PanelBar widget with DataSource in AngularJS.

Example
  <div ng-app="foo">
      <div ng-controller="MyCtrl">
        <ul kendo-panel-bar k-data-source="panelBarDataSource"></ul>
      </div>
  </div>

  <script>
    angular.module("foo", [ "kendo.directives" ]).controller("MyCtrl", function($scope) {
      $scope.panelBarDataSource = [
        {
          text: "Item 1 (link)",
          cssClass: "myClass",                            // Add custom CSS class to the item, optional, added 2012 Q3 SP1.
          url: "http://www.kendoui.com/"                  // link URL if navigation is needed (optional)
        },
        {
          text: "<b>Item 2</b>",
          encoded: false,                                 // Allows use of HTML for item text
          content: "text"                                 // content within an item
        },
        {
          text: "Item 3",
          // content URL to load within an item
          contentUrl: "https://demos.telerik.com/kendo-ui/content/web/panelbar/ajax/ajaxContent1.html"
        },
        {
          text: "Item 4",
          // item image URL, optional
          imageUrl: "https://demos.telerik.com/kendo-ui/content/shared/icons/sports/baseball.png",
          expanded: true,                                 // item is rendered expanded
          items: [{                                       // Sub item collection.
            text: "Sub Item 1"
          },
                  {
                    text: "Sub Item 2"
                  }]
        },
        {
          text: "Item 5"
        }
      ]
    });
  </script>

The following example demonstrates a Kendo UI TabStrip widget with DataSource in AngularJS.

Example
  <div ng-app="foo">
    <div ng-controller="MyCtrl">
      <div kendo-tab-strip k-data-source="tabStripDataSource" k-data-text-field="'text'" k-data-content-field="'content'"></div>
    </div>
  </div>

  <script>
    angular.module("foo", [ "kendo.directives" ]).controller("MyCtrl", function($scope) {
      $scope.foo = "Hello from angular";

      $scope.tabStripDataSource = [
        {
          text: "Item 1",
          content: "Item 1 content - "
        },
        {
          text: "Item 2",
          content: "Item 2 content - "
        }
      ]
    });

  </script>

The following example demonstrates a Kendo UI Menu widget with DataSource in AngularJS.

Example
    <div ng-app="foo">
        <div ng-controller="MyCtrl">
            <div kendo-menu k-data-source="menuDataSource"></div>
        </div>
    </div>

    <script>
        angular.module("foo", [ "kendo.directives" ]).controller("MyCtrl", function($scope) {
            $scope.foo = "Hello from angular";

            $scope.menuDataSource = [{
                text: "Item 1 ",
                cssClass: "myClass",
                url: "http://www.kendoui.com"
            },
            {
                text: "<b>Item 2</b>",
                encoded: false
            },
            {
                text: "Item 3",
                items: [{
                    text: "Sub Item 1"
                },
                {
                    text: "Sub Item 2"
                }]
            },
            {
                text: "Item 4",
                spriteCssClass: "imageClass3"
            }];
        });

    </script>

The k-ng-delay Option

If you need to avoid the generation of content with DataSource, you can implement a possible workaround by using the k-ng-delay configuration option.

Important

The approach is not recommended and results in side effects, such as FOUC (flash of unstyled content) and decreased performance.

The following example demonstrates a Kendo UI TabStrip widget in AngularJS with delayed initialization.

Example
<div id="example" ng-app="KendoDemos">
    <div class="demo-section k-content">
        <div ng-controller="MyCtrl">
            <div kendo-tab-strip k-ng-delay="tabStripDelay">
              <!-- tab list -->
              <ul>
                <li ng-repeat="tab in tabs"></li>
              </ul>

              <div ng-repeat="tabContent in tabContents">

              </div>

            </div>
        </div>
    </div>
</div>

<script>
  angular.module("KendoDemos", [ "kendo.directives" ])
      .controller("MyCtrl", function($scope, $timeout){
          $scope.tabs = [ "t1", "t2" ];
          $scope.tabContents = [ "tc1", "tc2" ];

                $timeout(function() {
            $scope.tabStripDelay = true;
          });
      })
</script>

The ng-if Directive

The ng-if directive, which is applicable to most ng-\* directives, operates directly on the origin HTML that is bound to and not on the widget itself. When the Kendo UI widget has a more complex rendering, such as the NumericTextBox, then the directive shows or hides the original input element and not the widget. This is expected due to the previously mentioned specifics of the ng-\* directives.

Important

The general solution is to use a specific k-ng-\ directive where available—for example, k-ng-disabled.

The following example demonstrates how to use a wrapping HTML element to hide/show Kendo UI Widget.

Example
<div id="example" ng-app="KendoDemos">
    <div class="demo-section k-content">
        <div ng-controller="MyCtrl">
            <div ng-if="show">
                <input kendo-numeric-text-box />
            </div>
        </div>
    </div>
</div>

<script>
  angular.module("KendoDemos", [ "kendo.directives" ])
      .controller("MyCtrl", function($scope, $timeout){
          $scope.show = false;
      })
</script>

See Also

Is this article helpful? Yes / No
Thank you for your feedback!

Give article feedback

Tell us how we can improve this article

close
Dummy