如何使用带有replace:true

时间:2016-02-23 17:19:10

标签: javascript angularjs

不删除 replace: true,如何在{* 1}}上使用ng-class而不会导致与模板ng-class发生错误/冲突?

目前,这会抛出以下Angular错误:

  

错误:语法错误:令牌' {'是第16列的意外标记   表达式[{custom:true} {custom:settings ==' custom',other:   设置=='其他'}]从[{custom:settings ==' custom',其他:   设置=='其他'}]

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: '=',
    }
  };
});

jsFiddle of this setup

3 个答案:

答案 0 :(得分:1)

研究角度编译,我们可以看到这是来自mergeTemplateAttributes函数的问题(你的jsFiddle使用的是v1.1.5,但这件作品甚至没有改变到v1。 5.0)。事实上,closed bug #7402引用了同样的问题。从该错误中引用@lgalfaso

  

我同意这是针对ng-class的一个问题,就像它在#7402 (comment)中所述的所有情况中都是一个问题一样。这是一个已知的错误和使用replace的指令限制:true

简而言之,如果没有一些解决方法,你就无法做到这一点。请注意,替换为DEPRECATED,因此您应该尝试删除replace: true。但是,你可以破解它对你有利。

您可以将函数传递给template,而不是传递字符串。该函数将使用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>'
},

这是example fiddle。如果您将someProperty更改为其他,则会看到它正确地将背景更改为黄色

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

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,因此必须在链接函数中添加它。这是另一个example fiddle.

答案 1 :(得分:0)

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

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-class成为:{custom:true,custom:settings ==&#39; custom&#39;,other:settings ==&#39; other&#39;}。

自定义条件被定义为第二个将控制的自定义条件。

答案 2 :(得分:0)

这是另一种解决方案(没有任何黑客攻击)

请参阅此处的工作示例: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/