具有双向绑定和ng-change的AngularJS指令

时间:2015-06-01 14:20:40

标签: javascript angularjs angularjs-directive

我遇到过一种情况,我需要根据下拉列表的选定值更改输入框的输入类型。换句话说,如果用户从下拉列表中选择“字符串”,那么输入的类型应该是“文本”等。我决定创建一个指令,因为我还在学习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

我使用this问题的答案来帮助我添加添加ng-change属性并正确触发的功能。根据该答案,我需要从孤立的范围中删除ngModel,我不确定为什么这是必需的,但是,如果有人能够解释它,我将不胜感激。

从隔离范围中删除ngModel使得使用初始值实例化指令变得更加困难,或者在主控制器中更改模型时更新指令,所以现在我看ngModel[0].$modelValue并更新本地值(如果它)变化。

虽然该指令有效且按照我的预期行事,但这一切看起来有点复杂和低效,难道我无法以更简单的方式实现我想要的目标吗?

1 个答案:

答案 0 :(得分:0)

使用second answer引用SO问题我解决了需要从隔离范围中删除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);
                });

            }
        };
    }
})();