如何使用带有替换的模板覆盖/补充指令中的ng类:true

How to override / compliment ng-class in a directive with a template with replace: true

本文关键字:指令 ng true 覆盖 何使用 替换      更新时间:2023-09-26

在不删除replace: true的情况下,如何在下面的指令中使用ng-class而不会导致错误/与模板ng-class冲突?

目前,这会引发以下角度错误:

错误:

语法错误:标记"{"是第 16 列中的意外标记 表达式 [{自定义:真} {自定义:设置=='自定义',其他: 设置=='其他'}] 从 [{自定义:设置=='自定义'开始,其他: 设置=='其他'}]。

.HTML

<div ng-app="MyApp" ng-controller="MyCtrl">
  <setting settings="settings.someProperty" 
    ng-class="{custom: true}" />
</div>

.JS

var myApp = angular.module('MyApp', []);
myApp.controller('MyCtrl', function($scope) {
  $scope.settings = {
    someProperty: ''
  }
});
myApp.directive('setting', function() {
  return {
    restrict: 'E',
    // Removing this is NOT an option
    replace: true,
    require: '^myCtrl',
    template: '<div ng-class="{myclass:settings==''custom'', other: settings==''other''}"><input type="radio"  name="mySetting" ng-model="settings" value="other" />TEST</div>',
    scope: {
      settings: '=',
    }
  };
});

这个设置的js小提琴

查看 angular 的编译,我们可以看到这是 mergeTemplateAttributes 函数的问题(您的 jsFiddle 使用了 v1.1.5,但这篇文章甚至没有改变到 v1.5.0)。实际上,有已关闭的错误#7402引用了相同的问题。引用该错误中的@lgalfaso

我同意这是 ng-class 的问题,就像在 #7402(评论)中所述的所有情况下都是一个问题一样,这是一个已知的错误和指令的限制 替换:true

简而言之,如果没有一些解决方法,您将无法执行此操作。请注意,替换已弃用,因此您应该真正尝试删除replace: true。但是,您可以破解它以对您有利。

您可以将函数传递给模板,而不是传递字符串。此函数将使用 tElement 和 tAttrs 执行。如果要完全替换该属性,将tAttrs.ngClass设置为空字符串将消除冲突。

template: function(tElement, tAttrs) {
        tAttrs.ngClass="";
        return '<div ng-class="{custom:settings==''custom'', other: settings==''other''}"><input type="radio"  name="mySetting" ng-model="settings" value="other" />TEST<br> <input type="radio"  name="mySetting" ng-model="settings" value="" />{{settings}}</div>'
},

这是一个小提琴的例子。如果将someProperty更改为其他,您将看到它正确地将背景更改为黄色


另一方面,如果要扩展/合并两个冲突指令的属性值,它将涉及更多,开销也更多。它仍然需要将tAttrs.ngClass设置为空字符串,但首先将其添加到ng类中,如下所示:

template: function(tElement, tAttrs) {
    var newNgClass = "{custom:settings==''custom'', other: settings==''other''}";
    var oldNgClass = tAttrs.ngClass;
    var mergedNgClass = "extend(" + oldNgClass + "," + newNgClass + ")";
    tAttrs.ngClass = "";
    return '<div ng-class="' + mergedNgClass + '"><input type="radio"  name="mySetting" ng-model="settings" value="other" />TEST<br> <input type="radio"  name="mySetting" ng-model="settings" value="" />{{settings}}</div>'
},
link: function(scope) {
    scope.extend = angular.extend;
}

这不是合并两个角度表达式字符串,而是依赖于不在作用域上的angular.extend,因此必须将其添加到链接函数中。这是另一个例子小提琴。

我不认为这是最好的方法,但你可以认为这是一个黑客

.HTML:

<div ng-app="MyApp" ng-controller="MyCtrl">
  <setting settings="settings.someProperty" 
    ng-class="{custom: true," />
</div>

脚本:

 var myApp = angular.module('MyApp', []);
myApp.controller('MyCtrl', function($scope) {
  $scope.settings = {
    someProperty: ''
  }
});
myApp.directive('setting', function() {
  return {
    restrict: 'E',
    // Removing this is NOT an option
    replace: true,
    require: '^myCtrl',
    template: '<div ng-class="custom:settings==''custom'', other: settings==''other''}"><input type="radio"  name="mySetting" ng-model="settings" value="other" />TEST</div>',
    scope: {
      settings: '=',
    }
  };
});

https://jsfiddle.net/3jcmLh0t/10/

ng 类变为 :{custom: true, custom:settings=='custom', other: settings=='other'} 。

自定义条件定义 2 次,第二个条件将控制。

这是

另一种解决方案(没有任何黑客)

请参阅此处的工作示例:https://jsfiddle.net/3gqjck49/4/

var myApp = angular.module('MyApp', []);
myApp.controller('MyCtrl', function($scope) {
  $scope.settings = {
    someProperty: ''
  }
});
myApp.directive('setting', function() {
   return {
   restrict: 'E',
   // Removing this is NOT an option
   replace: true,
   require: '^myCtrl',
   template: '<div ng-class="{custom:settings==''custom'', other: settings==''other''}"><input type="radio"  name="mySetting" ng-model="settings" value="custom" />TEST<br> <input type="radio"  name="mySetting" ng-model="settings" value="other" />{{settings}}</div>',
   scope: {
     settings: '=',
   }
  };
});

https://jsfiddle.net/3gqjck49/4/