指令动态更改颜色和文字

时间:2018-03-12 13:00:35

标签: angularjs-directive

这是一个指令,应根据传入数据

更改元素的颜色和文本
function colorStatus() {
        return {
            restrict: 'AE',
            scope: {
                status: '@'
            },
            link: function (scope, element) {
            let status = +scope.status;
            switch (status) {
                case 0:
                    element.text(' ');
                    element.css('color', '#FFFFFF');
                    break;
                case 1:
                    element.text('Correct!');
                    element.css('color', '#4CAF50');
                    break;
                case 2:
                    element.text('Error!');
                    element.css('color', '#F44336');
                    break;
                case 3:
                    element.text('Waiting...');
                    element.css('color', '#FF9800');
                    break;
            }
        }
    };
}

最初,它从控制器接收已解析的数据。

这是HTML:

<color-status status="{{vm.status}}"></color-status>
<button ng-click="vm.changeStatus()"><button>

这是来自控制器的功能:

vm.changeStatus = changeStatus;
vm.status = chosenTask.status;  // It equals 0 in the received data

function changeStatus() {
    vm.status = 1;
}

我希望指令的文字和颜色会改变,但这不会发生。我的错误在哪里?

1 个答案:

答案 0 :(得分:0)

仅发送一次

后链接

您遇到的问题是您在link功能中设置了元素的文字和颜色。这意味着当你的指令实例化并进行初始化时,link函数将被执行,但它将被执行一次。当status的值发生变化时,您不会处理这些更改以反映您的元素。因此,您应该将$onChanges()函数添加到您的指令并处理这些更改。

function StatusController($element) {
    this.$element = $element;
    this.status = 0;
}

StatusController.mapper = [
    { text: ' ', color: '#FFFFFF' },
    { text: 'Correct!', color: '#4CAF50' },
    { text: 'Error!', color: '#F44336' },
    { text: 'Waiting...', color: '#FF9800' },
}];

StatusController.prototype.setStatus = function(status) {
    var statusObj = StatusController.mapper[+status];
    this.$element
        .text(statusObj.text)
        .css('color', statusObj.color);
}

StatusController.prototype.$onInit = function() {
    // this.status is now populated by the supplied attribute value
    this.setStatus(this.status);
}

StatusController.prototype.$onChanges = function(changes) {
    if (changes.status && !changes.status.isFirstChange()) {
        this.setStatus(this.status);
    }
}

var StatusDirective = {
    restrict: 'AE',
    controller: StatusController,
    scope: true,
    bindToController: {
        status: '@'
    }
};

angular.module('someModule')
       .directive('colorStatus', function() { return StatusDirective; });

但除此之外,我还建议您使用ng-bind{{...}}设置元素的文本以将该值放入。指令可以填充其公共属性,并在HTML中使用它们和CSS一起。如果可能的话,从AngularJS代码中操纵DOM元素总是更明智。

function StatusController($element) {
    this.$element = $element;
    this.status = 0;
    this.text = '';
    this.name = '';
}

StatusController.mapper = [
    { text: ' ', name: '' },
    { text: 'Correct!', name: 'correct' },
    { text: 'Error!', name: '#error' },
    { text: 'Waiting...', name: 'pending' },
}];

StatusController.prototype.setStatus = function(status) {
    var statusObj = StatusController.mapper[+status];
    this.text = statusObj.text;
    this.name = statusObj.name;
}

StatusController.prototype.$onInit = function() {
    // this.status is now populated by the supplied attribute value
    this.setStatus(this.status);
}

StatusController.prototype.$onChanges = function(changes) {
    if (changes.status && !changes.status.isFirstChange()) {
        this.setStatus(this.status);
    }
}

var StatusDirective = {
    restrict: 'AE',
    controller: StatusController,
    controllerAs: 'colorStatus',
    scope: true,
    bindToController: {
        status: '@'
    }
};

angular.module('someModule')
       .directive('colorStatus', function() { return StatusDirective; });

然后在你的模板中写这样使用它:

<color-status status="{{vm.status}}" ng-class="colorStatus.name" ng-bind="colorStatus.text"></color-status>

这将为您提供更多模板灵活性。除了在控制器中设置文本之外,您可以只使用类名并使用伪类向元素添加文本,但是您可以这样做,因此<color-status>指令的每个实例都可以以相同的状态显示值。