AngularJs 切换 templateUrl 并访问模型数据

AngularJs switch templateUrl and access modeldata

我需要在指令中切换模板 URL,并且我必须传输一些模型数据。

我试过使用函数来切换模板,例如:

.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>';
         } 
      }
   },

那没有用,因为 tAttrs 值是一个表达式,在这里我只得到了表达式的字符串值,如“{{item.WidgetConfig.WidgetType}}”,而不是值本身。

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

然后我尝试在 link 函数中使用 ngInclude 和 switch 模板。 (html里面的模板和上面模板函数里的一样)

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

这似乎可行,但现在我遇到了一个问题,我不知道如何将我的模型值传递给我在包含中加载的指令。我认为它应该适用于 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);;
            }
        }
    }
})

但我只得到一个错误,找不到控制器 "sqGridData"。有没有更好的方法来解决这类问题或者有人知道我做错了什么?

这可以通过一个指令解决,一个基于属性值的 templateUrl 切换模板的函数,一个具有传递的模型值的通用名称的范围,以及一个调用指令的 ng-switch,而不是在指令中。

您的 html 会打开类型,其中“-when”是类型的值。

<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>

你的指令看起来像"like"这个...

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

如果你想要更少的代码,以及一个不太灵活、懒惰的编码器版本,其中模板专门针对类型命名,你可以这样做...

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

现在,在您的模板中,您需要为您希望在两个模板中的指令隔离范围内可用的范围值使用通用名称。

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

然后所有的魔法都击中了扇子。

我找到了解决问题的方法。

使用指令:

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

在我的 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";
              }
          }
      }
  })

我需要申报

scope.sqGridData = scope.sqGridData;

我不知道是否有更好的解决方案,但这是从具有范围的子指令访问范围 属性 的唯一方法。$parent - 是否有更好的解决方案 (我试过 require 属性 但这没有用)?

"widget.directives.iFrame.html"

的模板内容
 <div sq-iframe></div>

"widget.directives.table.html"

的模板内容
<div sq-table></div>

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