【问题标题】:AngularJs - bind one ng-model to directive with two inputsAngularJs - 将一个 ng-model 绑定到具有两个输入的指令
【发布时间】:2014-09-28 06:57:30
【问题描述】:

如何创建一个range 指令,该指令绑定到一个ng-model 并使用filter 输出两个input 字段(已创建)。基本上我有一个方向从模型到输入工作,但另一侧从输入到模型没有。如何做到这一点?

我有这个 Html:

<div tu-range ng-model="arbitraymodel" />

还有一个模型:

var arbitrarymodel = "10/22";

旁注;我创建了一个过滤器来拆分这两个值:
{{ feature.Value | split:\'/\':0}}

还有这个指令:

.directive('tuRange', function($compile) {
    return { 
        restrict: 'A',
        require: 'ngModel',
        scope: {
            feature: '=',
            tudisabled: '=',
            model: '=ngModel' // edited
        },
        template: '<input type="text" '+
               'ng-value="{{ model | split:\'/\':0}}" />'+ // edited to 'model'
             '-<input type="text" '+
               'ng-value="{{ model | split:\'/\':1}}" />', // edited to 'model'
        link: function(scope, element, attributes, ngModel) {

        }
    };
})

【问题讨论】:

  • 你真的需要10/22的值来做吗?为什么不使用带有arbitrary.beginarbitrary.end 键的对象呢?如果需要,可以使用更改侦听器将两者组合回一个值。
  • hm,对此不太确定,但是他如何反转双向绑定的过滤?
  • 我对添加model的指令范围做了一个小改动。 @ConcurrentHashMap 是的,这不是我得到的最佳数据。但最终它必须以这种方式发回,所以为了确保一切都发生在一个地方,我想在指令中这样做。

标签: javascript angularjs angularjs-filter angular-directive


【解决方案1】:

正确的方法 (IMO) 是创建自定义控件,如 here 所述。

作为练习,我在这个小提琴中实现了它:http://jsfiddle.net/6cn7y/

指令的代码是(你可能需要调整一些细节):

app.directive("range", function() {
    var ID=0;

    function constructRangeString(from, to) {
        var result;
        if( !from && !to ) {
            result = null;
        }
        else if( from ) {
            result = from + "/" + (to || "");
        }
        else if( to ) {
            result = "/" + to;
        }
        return result;
    }

    return {
        require: "ngModel",
        restrict: "E",
        replace: true,
        scope: {
            name: "@"
        },
        template:
            '<div ng-form="{{ subFormName }}">' +
                '<input type="text" ng-model="from" class="range-from" />' +
                '<input type="text" ng-model="to" class="range-to" />' +
            '</div>',
        link: function(scope,elem,attrs,ngModel) {
            var re = /([0-9]+)\/([0-9]+)/;

            if( scope.name ) {
                scope.subFormName = scope.name;
            }
            else {
                scope.subFormName = "_range" + ID;
                ID++;
            }

            ngModel.$render = function() {
                var result, from, to;
                result = re.exec(ngModel.$viewValue);
                if( result ) {
                    from = parseInt(result[1]);
                    to = parseInt(result[2]);
                }
                scope.from = from;
                scope.to = to;
            };

            scope.$watch("from", function(newval) {
                var result = constructRangeString(newval, scope.to);
                ngModel.$setViewValue(result);
            });
            scope.$watch("to", function(newval) {
                var result = constructRangeString(scope.from, newval);
                ngModel.$setViewValue(result);
            });
        }
    };
});

它的用法是:

<range ng-model="ctrl.theRange" name="myRange" required="true"></range>

我怀疑过滤器不会带你到任何地方,因为它们不进行双向绑定。


编辑:尽管这解决了问题,但我建议采用稍微不同的方法。我会将range 指令的模型定义为一个对象:

{
    from: ...,
    to:   ...
}

这意味着示例中ctrl.theRange 变量中的输出将是与上述类似的对象。如果您真的想要字符串格式"from/to",请在ngModel 管道中添加解析器/格式化程序,即constructRangeString() 函数。使用解析器/格式化程序,ctrl.theRange 变量获得所需的字符串格式,同时保持代码更加模块化(constructRangeString() 函数在指令外部)和更多参数化(模型采用易于处理的格式并转化)。

还有一个概念证明:http://jsfiddle.net/W99rX/

【讨论】:

  • 哇,做得很好。我特别喜欢第二种方式,它确实更加模块化,因此也可以更好地测试。非常感谢!
  • Few cmets: 1. 如果您填写“0”,则模型为空,因为您检查if(!from &amp;&amp; !to) return null; 导致模型为空。 2. 使用大约 180 个范围时(因为它是数据网格),速度很慢。
  • 1.是的,我期待一些粗糙的边缘。另一个可能是正则表达式。你可能需要unshift() 来自$formatters 而不是pushing - 我一直对此感到困惑。 2. 这很有趣(也很不幸)。我会尝试的一种优化是直接使用 DOM 事件获取视图值,而不是使用嵌套表单和 ng-models。这将减少手表,但会使代码复杂化。另一个优化是尝试用 "from""to" 的 2 个单独的 watch 替换 deep watch。我不指望它有多大作用,但你永远不知道。
  • 感谢您的回复。我尝试了一些优化,也删除了RexExp,但最终速度很慢。所以我拿了我通过$http() 得到的集合并使用value.split('/') 修改了值(有一些检查)并将其放入全局model.from/.to,即使现在它仍然很慢。所以我想我必须应付它。或者也许只使用ng-blur 更新model 来更新值。我必须看看该怎么做:)。到目前为止非常感谢你:)
  • 上面引用的 jsFiddle (jsfiddle.net/W99rX) 适用于 Angular 版本 1.2.x 但我发现我无法让它在 Angular 1.4.x 中工作 在阅读了一些文档后,我更改了读取 ngModel.$setViewValue(newval); 的行到 ngModel.$setViewValue(angular.copy(newval));它按预期工作。
猜你喜欢
  • 2014-11-21
  • 2014-06-21
  • 2016-11-18
  • 2015-12-20
  • 1970-01-01
  • 1970-01-01
  • 2021-01-19
  • 1970-01-01
  • 2012-12-16
相关资源
最近更新 更多