【问题标题】:How to use an ngModel with a custom directive in AngularJS如何在 AngularJS 中使用带有自定义指令的 ngModel
【发布时间】:2014-03-15 07:03:17
【问题描述】:

我的指令:

(function () {
  'use strict';

  wikiApp.directive('jzInput', ['$sce', function ($sce) {
    var html = [
      '<input type="text" ng-change="validate()" />'
    ];

    var addSeparator = function (input, sep) {
      return (input + '').replace(/(\d)(?=(\d{3})+$)/g, '$1' + sep);
    };

    var digitsOnly = function (input) {
      return (input.toString()).replace(/[^\d]/g, "");
    };

    var parseInteger = function(input) {
      return addSeparator(digitsOnly(input), ',');
    };

    return {
      restrict: 'E',
      template: html.join(''),
      replace: true,
      require: 'ngModel',
      scope: {
        type: '@'
      },
      link: function($scope, $element, $attr, ngModel) {

      ngModel.$parsers.push(function(value){
        var input = value;
        var output = input;

        // Integer
        output = parseInteger(input);

        console.log(output);
        return output;
      });

      }
    };
  }]);
})();

我的 HTML:

<jz-input type="text" ng-model="test">
<input type="text" ng-model="test">

input 具有来自我的 validate 函数的更新值,而我的 jzInput 指令没有。如何从我的指令中手动更新 ngModel 的值并使其正确反映?

例子:

Plunker。在顶部输入中输入数字和字母。请注意,字母会出现,而格式良好的数字则不会。在下面的输入中,使用相同的模型变量,显示了正确的预期值。如何让我的jz-input 显示模型的正确预期值?

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    我希望这是您对指令的期望。刚刚对您的代码进行了一些更改。

     module.directive('jzInput', [function () {
    var html = [
      '<input type="text" />'
    ];
    
    var addSeparator = function (input, sep) {
      return (input + '').replace(/(\d)(?=(\d{3})+$)/g, '$1' + sep);
    };
    
    var digitsOnly = function (input) {
      return (input.toString()).replace(/[^\d]/g, "");
    };
    
    var parseInteger = function(input) {
      return addSeparator(digitsOnly(input), ',');
    };
    
    return {
      restrict: 'E',
      template: html.join(''),
      replace: true,
      require: 'ngModel',
      scope: {
        test: '=ngModel'
      },
      link: function(scope, element, attr) {
    
    scope.$watch('test',function(newVal){
    
        if(newVal != undefined) {
            scope.test = parseInteger(newVal);
        }
    });
    
      }
    };
      }]);
    

    【讨论】:

    • 嗨,您正在观看 scope.test。问题是我不知道模型是否为test。该指令的用户可以传递他们喜欢的任何东西作为模型。
    • 我想我误解了你的要求。但在上面的代码中,我正在观看与 ng-model 绑定的测试。请找到演示plnkr.co/edit/8PbgvnUVF6rLhbqJb0HN?p=preview
    • @Justin808 这个例子中的“测试”是完全任意的。如果是 scope: { linkedModel: '=ngModel' } scope.$watch('linkedModel', function(newVal) { 这样更清楚吗?
    【解决方案2】:

    使用 ngModel 实现验证的正确方法是在其 parsers 集合中添加一个函数。

    ngModel.$parsers.push(function(value){
         var input = value;
         var output = input;
    
         // Integer
         output = parseInteger(input);
         console.log(output);
         return output;
    });
    

    我还对您的代码进行了一些更改:

    • 将指令用作属性而不是元素:restrict: 'A'
    • function ($sce) { 更改为['$sce',function ($sce) {

    DEMO

    【讨论】:

    • 嗨,我试过你的代码,但它不工作。我添加了一个 Plunker 演示,所以你可以看到发生了什么。
    • @Justin808:解析器的返回值 (return output;) 是为您的基础模型设置的值。也许我不完全理解您的要求,但是您可以更改函数以返回您想要的值,如果输入值无效则返回 undefined。
    • @Justin808:什么不起作用?我试图再次阅读问题,但我仍然不明白您的要求。你能更详细地解释一下吗?在这段代码中,parseInteger(input); 删除了input 中的所有字母,并返回设置为您的 ngModel 基础属性的值。 (预期行为)
    猜你喜欢
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多