清除$destroy上的指令作用域变量

Clearing directive scope variables on $destroy

本文关键字:指令 作用域 变量 destroy 清除      更新时间:2023-09-26

在我的单选按钮上,我有一个绑定到change事件的指令,并设置在具有单选按钮值的元素上定义的ngModel。这很好。

然而,单选按钮可以根据用户的选择从DOM中删除隐藏,当这种情况发生时,我想清除控制器中的这些变量。我有一个$destroy事件的处理程序,我将范围ngModel值设置为undefined

由于某种原因,设置$destroy中的范围值没有在我的控制器中更改,而在change处理程序中设置它。

:

<div ng-repeat="item in category.items" class="field">
    <div class="ui radio checkbox">
        <input type="radio" value="{{item}}" sm-radio-button ng-model="submissions[category.model]" name="{{category.name}}" checked="" tabindex="0" class="hidden">
        <label ng-bind="item"></label>
    </div>
</div>

指令:

.directive('smRadioButton', function(){
    return {
        scope: {
            ngModel: '='
        },
        link: function(scope, element, attrs){
            //Instantiate checkbox on load and set value to undefined
            element.parent().checkbox();
            scope.ngModel = undefined;

            element.on('$destroy', function(){
              scope.ngModel = undefined;
            })            
            element.on('change', function(e){
                scope.$apply(function(){
                    scope.ngModel = attrs.value;
                });
            });
        }
    };
})

其中category是众多配置对象之一,如:

  {
    name: 'Type',
    model: 'type',
    alwaysShow: true,
    items: ['Spending','Bills','Account Transfer','Deposit']
  }, 

注意:我没有在$destroy中使用scope.$apply,因为已经有一个消化循环在进行中。$destroy正在被触发

Edit:在其他几个元素上测试了这一点,似乎在$destroy中只有什么似乎是该变量的局部范围被改变了?如果我通过scope.$parent直接引用控制器,控制器变量确实会改变。(这是不理想的,因为这是几个ng-repeat深度,这意味着链接一堆$parent s)

您应该使用NgModelController方法。

摘自NgModelController文档:

NgModelController为ngModel指令提供了API。控制器包含用于数据绑定、验证、CSS更新以及值格式化和解析的服务。它故意不包含任何处理DOM呈现或监听DOM事件的逻辑。这些与DOM相关的逻辑应该由其他使用NgModelController进行数据绑定到控制元素的指令提供。Angular为大多数输入元素提供了这种DOM逻辑。在本页的末尾,你可以找到一个自定义控件的例子,它使用ngModelController来绑定可满足内容的元素。

您应该使用$setViewValue,然后,如上所示,由于API的性质,您需要调用$render来更新视图:

.directive('smRadioButton', function(){
    return {
        scope: {
            ngModel: '='
        },
        link: function(scope, element, attrs, ctrl){
            //Instantiate checkbox on load and set value to undefined
            element.parent().checkbox();
            // set the view value
            ctrl.$setViewValue(undefined);
            // render the changes
            ngModel.$render();
            element.on('$destroy', function(){
              ctrl.$setViewValue(undefined);
              ngModel.$render();
            });
            element.on('change', function(e){
                ctrl.$setViewValue(attrs.value);
                ngModel.$render();
            });
        }
    };
});

为了设置ngModel值,你可以使用ngModel.$setViewvalue(undefined),但同样的,你必须要求ngModel在指令的link函数中获取ngModelController

也可以使用$parse API将值设置为ngModel指令(不需要ngModel控制器那里的指令)。

所以你可以摆脱isolated scope(不确定这个指令到底在做什么,如果它是你只在代码中显示的,那么就不需要隔离)

指令

.directive('smRadioButton', function(){
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel){
            //var getter = $parse($attrs.ngModel);
            //setter = getter.assign;
            //Instantiate checkbox on load and set value to undefined
            element.parent().checkbox();
            element.on('$destroy', function(){
              ngModel.$setViewValue(undefined);
              //setter($scope, undefined);
            })            
            element.on('change', function(e){
                scope.$apply(function(){
                    ngModel.$setViewValue(attrs.value);
                    //setter($scope, attrs.value);
                });
            });
        }
    };
})