使用双向绑定和ng-change的AngularJS指令

AngularJS directive with two-way binding and ng-change

本文关键字:ng-change AngularJS 指令 绑定      更新时间:2023-09-26

我遇到了一种情况,我需要根据下拉框的选定值更改输入框的输入类型。换句话说,如果用户从下拉菜单中选择了'String',那么输入的类型应该是'text',等等。我决定创建一个指令,因为我还在学习Angular,但也不想到处复制代码块(我需要不止一次)。

这是我尝试的内容:

(function () {
    "use strict";
    angular
        .module('app')
        .directive('dynamicTypeInput', dynamicTypeInput);
    function dynamicTypeInput() {
        return {
            replace: true,
            restrict: 'AE',
            require: ['ngModel', '^form'],
            scope: {type: '=', placeholder: '@'},
            templateUrl: 'app/common/dynamic-type-input/dynamic-type-input.tpl.html',
            link : function(scope, element, attrs, ngModel){
                //Watch for changes to ngModel, update scope.inputValue
                scope.$watch(function(){
                    return ngModel[0].$modelValue;
                }, function (value){
                    scope.inputValue = value;
                });
                //Watch inputValue, update the model
                scope.$watch('inputValue', function(value){
                    ngModel[0].$setViewValue(value);
                });
                //Setup ng-change
                if (attrs.ngChange) {
                    ngModel[0].$viewChangeListeners.push(function () {
                        scope.$eval(attrs.ngChange);
                    });
                }
            }
        };
    }
})();

注意:模板是一个简单的ng-switch,根据scope.type的值选择合适的输入框,所有的输入都绑定到scope.inputValue

我使用这个问题的答案来帮助我添加添加ng-change属性和正确射击的能力。根据这个答案,我需要从孤立的作用域中删除ngModel,我不确定为什么需要这样做,但是,如果有人能解释一下,我会很感激。

从隔离的作用域中删除ngModel使得用初始值实例化指令或在主控制器中更改模型时更新指令变得更加困难,所以现在我观察ngModel[0].$modelValue并在它更改时更新本地值。

虽然指令的工作和做什么我期望它做,但它似乎有点复杂和低效,有没有办法我可以实现我想要一个更简单的方式?

使用引用的第二个问题的答案,我修复了需要从隔离的作用域中删除ngModel以使ngChange工作的问题。这简化了指令,我可以按原样使用双向绑定。

最后的指令:

(function () {
    "use strict";
    angular
        .module('app')
        .directive('dynamicTypeInput', dynamicTypeInput);
    dynamicTypeInput.$inject = ['$timeout'];
    function dynamicTypeInput($timeout) {
        return {
            replace: true,
            restrict: 'AE',
            require: ['ngModel', '^form'],
            scope: {ngModel: '=', type: '=', placeholder: '@', ngChange: "&"},
            templateUrl: 'app/common/dynamic-type-input/dynamic-type-input.tpl.html',
            link: function (scope, element, attrs, ngModel) {
                scope.$watch('ngModel', function () {
                    $timeout(scope.ngChange);
                });
            }
        };
    }
})();