AngularJs切换templateUrl并访问modeldata

时间:2015-03-13 22:27:36

标签: javascript angularjs angularjs-directive angularjs-scope

我需要在我的指令中切换模板URL,我必须传输一些modeldata。

我尝试使用函数切换模板,如:

.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值是一个表达式,在这里我只得到表达式的字符串值,如&#34; {{item.WidgetConfig.WidgetType}}&#34;而不是价值本身。

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

然后我尝试在链接功能中使用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);;
            }
        }
    }
})

但我只得到一个错误,那就是Controller&#34; sqGridData&#34;无法找到。有没有更好的方法来解决这类问题,或者有人知道我做错了什么?

2 个答案:

答案 0 :(得分:0)

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

你的html会打开类型,其中&#34; -when&#34;是类型的值。

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

你的指令看起来像&#34;喜欢&#34;此...

.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 如果您想要更少的代码,以及灵活性较低的懒惰编码器版本,其中模板专门为Type命名,您可以这样做...

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

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

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

然后所有魔法都击中了粉丝。

答案 1 :(得分:0)

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

使用指令:

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

在我的模板/指令之间切换的指令

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;

我不知道是否有更好的解决方案,但这是从带有范围的子指令访问scope属性的唯一方法。$ 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;
          });
        }
      }
    })