AngularJs switch templateUrl and access modeldata

I need to switch the template URL in my directive and I have to transfer some modeldata.

I've tried to use a function to switch the template like:

.directive("sqGridData", function ($sce, $rootScope, angularProxySrv) {
   return {
   ...
    template: function (tElement, tAttrs) {
      //Not working got Exception
      //var val = $rootScope.$eval(tAttrs.sqType);

      if (tAttrs.sqType) {
         if (tAttrs.sqType === 'Iframe') {
             return '<div sq-iframe ></div>';
         }
         if (tAttrs.sqType === 'Table') {
             return '<div sq-table></div>';
         } 
      }
   },

that did not work, because the tAttrs value was a expression and here I only got the string value of the expression like "{{item.WidgetConfig.WidgetType}}" and not the Value itself.

 <div style="height: 90%;" sq-grid-data="item.WidgetConfig" sq-type="{{item.WidgetConfig.WidgetType}}"></div>

then I've tried to use ngInclude and switch template in the link function. (The templates in the html are the same like above in the template function)

template: '<div ng-include="cntUrl" style="height:100%;"></div>',
link: function (scope, elem, attr) {
   var wasCalled = false;
   if (!wasCalled) {
       wasCalled = true;

      if (scope.sqGridData.WidgetType === 'Iframe') {
         scope.cntUrl = "/Templates/widget.directives.iFrame.html";
      }
      if (scope.sqGridData.WidgetType === 'Table') {
         scope.cntUrl = "/Templates/widget.directives.table.html";
      }
  }
}

that seems to work, but now I've the problem I don't know how to pass my modelvalues to my directives I've loaded in the include. I thought it should work with require:

.directive("sqIframe", function ($sce) {
    return {
        restrict: "A",
        require: "^sqGridData",
        template: '<div style="height:100%;"></div>',
        scope: {
            sqIframe: "="
        },
        link: function (scope, elem, attr, ngModel) {
              scope.cntUrl = "Home/WidgetHtmlTemplate?name=" + ngModel.HtmlTemplateName;
               scope.IframeUrl = $sce.trustAsResourceUrl(ngModel.WidgetName);;
            }
        }
    }
})

but I only get an error, that the Controller "sqGridData" can't be found. Is there a better way to solve this kind of Problem or someone knows what I am making wrong?

This can be solved with a single directive, a function for templateUrl switching templates based on an attribute value, a scope with a generic name for the model value passed, and an ng-switch where the directive is called, not in the directive.

Your html would switch on type, where the "-when" is the value of the type.

<div ng-switch="item.WidgetConfig.WidgetType">
    <div ng-switch-when="Iframe">
         <div sq-grid-data template="Iframe" modelvalue="item.WidgetConfig"></div>
    </div>
    <div ng-switch-when="Table">
         <div sq-grid-data template="Table" modelvalue="item.WidgetConfig"></div>
    </div>
</div>

Your directive would look something "like" this...

.directive('sqGridData', function () {
    //Returns the desired template based on the 'template" attribute value
    return {
        restrict: 'EA',
        replace: true,
        scope: {
            modelval: '=modelvalue'
        },
        templateUrl: function (elem, attr) {
            switch (attr.template) {
                case 'Iframe':
                    return "/Templates/widget.directives.iFrame.html";
                case 'Table':
                    return "/Templates/widget.directives.table.html";
                default:
                    return null;
            }                
        }
    };
});

OR if you want less code, and a less flexible, lazy coder version, where the template is NAMED specifically to the Type, you could do this...

templateUrl: function (elem, attr) { return '/Templates/widget.directives.' + attr.template + '.html"; }

Now in your templates, you will need to use the generic name for the scope value you wanted available on your directives isolated scope in both templates.

<div>
     <span>{{ modelval.imaStringPropertyOnTheItemWidgetConfig }} </span>
</div>

Then all the magic hits the fan.

I've found an solution for my problem.

Using the Directive:

<div style="height: 90%;" sq-grid-data="item.WidgetConfig"></div>

A directive to switch between my templates/directives

angular.module("widget.directives", ["angularProxySrv"])
    .directive("sqGridData", function () {
        return {
          restrict: 'A',
          template: '<div ng-include="cntUrl" style="height:100%;"></div>',
          scope: {
              sqGridData: "="
          },
          link: function (scope, elem, attr) {
              scope.sqGridData = scope.sqGridData;

              if (scope.sqGridData.WidgetType === 'Iframe') {
                  scope.cntUrl = "Templates/widget.directives.iFrame.html";
              }

              if (scope.sqGridData.WidgetType === 'Table') {
                  scope.cntUrl = "Templates/widget.directives.table.html";
              }
          }
      }
  })

I need to declare the

scope.sqGridData = scope.sqGridData;

I don't know if there is a better solution, but this was the only way to access the scope property from the child directive with the scope.$parent - is there perhaps a better solution (I've tried the require property but this did not work)?

The Templates content for "widget.directives.iFrame.html"

 <div sq-iframe></div>

The Templates content for "widget.directives.table.html"

<div sq-table></div>

The Directive for the sqTable

.directive("sqTable", function (angularProxySrv) {
    return {
          restrict: "A",
          replace: true,
          template: '<div ng-include="cntUrl" style="height:100%;"></div>',
          scope: true,
          link: function (scope, elem, attr, ngModel) {
              scope.cntUrl = "Home/WidgetHtmlTemplate?name=" + scope.$parent.sqGridData.HtmlTemplateName;
              angularProxySrv.LoadWidgetDataByWidgetName(scope.$parent.sqGridData.WidgetName).then(function (data) {
              scope.Data = data;
          });
        }
      }
    })