AngularJS - 指令的类名不能带入内部模板

时间:2017-09-19 08:55:34

标签: javascript angularjs angularjs-directive

我想制定一个有条件地接受类名的指令。但是,我发现只有将类名硬编码到class属性中时,我的代码才能工作。如果我尝试将它与任何表达式一起使用,它就无法工作。

例如

// HTML

// Doesn't work (cannot find class="editable" in the final output template)
<tit-txt ng-class="true ? 'editable' : ''" ng-model="mdEnt.phone"></tit-txt>

// Works! (I can find class="editable" in the final output template)
<tit-txt class="editable" ng-model="mdEnt.phone"></tit-txt>
//JS

.directive('titTxt', function () {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
        },
        link: function (scope, element, attrs) {
            scope.editable = element.hasClass('editable') ? 'editable' : '';
        },
        template: '<input ng-class="editable" ng-model="ngModel" />',
    };
})

任何人都可以向我解释为什么会这样?我如何在表达中使用它?

更新1

// HTML

// Doesn't work
<tit-txt ng-class="{'editable': true}" ng-model="mdEnt.phone"></tit-txt>
//JS

.directive('titTxt', function () {
    return {
        restrict: 'E',
        scope: {
            title: '@',
            fieldName: '@',
            ngModel: '=',
        },
        link: function (scope, element, attrs) {
            console.log(element.hasClass('editable'));
            scope.editable = element.hasClass('editable') ? 'editable' : '';
        },
        template: '<div><span>{{title}}: </span><input id="{{fieldName}}" ng-class="{editable: true}" name="{{fieldName}}" ng-model="ngModel" /></div>',
    };
})

任何人都可以向我解释为什么我会在console.log(element.hasClass('editable'));中获得 false

1 个答案:

答案 0 :(得分:0)

使用class属性,元素的类由JavaScript设置。使用ng-class指令,该类由AngularJS框架设置。如果元素上有多个指令,则无法保证各指令代码的执行顺序。

避免让AngularJS操纵DOM并让后续的AngularJS根据DOM的状态操纵模型。对于MVC框架,模型应该是single source of truth,DOM应该由模型直接确定。

<tit-txt inner-class="true ? 'editable' : ''" my-model="mdEnt.phone">
</tit-txt>
app.directive('titTxt', function () {
    return {
        restrict: 'E',
        scope: {
            title: '@',
            fieldName: '@',
            innerClass: '<',
            myModel: '=',
        },
        link: function (scope, element, attrs) {
            scope.$watch(attrs.innerClass, function(newValue) {
                console.log("inner-class=", newValue);
            });
        },
        template: `<div><span>{{title}}: </span>
                      <input id="{{fieldName}}" ng-class="innerClass"
                             name="{{fieldName}}" ng-model="myModel" />
                   </div>`,
    };
})

请注意该指令如何使用one-way, '<', binding来计算AngularJS Expressioninner-class属性的值。

另请注意,我已将ng-model更改为my-modelng-前缀保留用于核心AngularJS指令。除非custom directivengModelController正确集成,否则应特别避免使用ng-model