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;
});
}
}
})