我可以使用ngModelController的$格式完全控制输入字段的呈现方式?可以使用、字段、格式、方式

2023-09-13 02:45:13 作者:风软一江水

我试图做一个模拟输入键入=号,但我想我自己的按钮添加到它。基本上,我做了

I am trying to make an input that simulates type="number" but I want to add my own buttons to it. Basically I've made

<form name="fasdf">
    <button class="btn" ng-click="decrement()">&#9668;</button>
    <input type="text" ng-model="model" display-as-number />
    <button class="btn" ng-click="increment()">&#9658;</button>
</form>

我用输入类型=文本,因为我不希望用户代理添加自己的按钮到外地。

I'm using input type="text" because I don't want the user agent to add it's own buttons to the field.

应该可以使用输入本身输入一个值以及使用的按钮来增加或减少值。

It should be possible to use the input itself to enter a value as well as using the buttons to increment or decrement the value.

angular.module('app',[])
.controller('Ctrl', ['$scope', function($scope) {

  $scope.model = 0;

  $scope.decrement = function() {
    $scope.model--;
  };

  $scope.increment = function() {
    $scope.model++;
  };

}])

该值是最初 0 但是,当用户开始输入文本我想为他们输入任何前导零被剥离(实际上西装希望这样,但你得到我的意思)。

The value is initially 0 but when the user starts entering text I want any leading zeros to be stripped as they type (well, actually the suits want that but you get my drift).

我的理论是,我可以使用 $格式和/或 $解析器通过这样做访问指令的 ngModelController

My theory was that I could use a $formatter and/or a $parser to do this by making a directive that accesses the ngModelController.

angular.module('app')
.directive('displayAsNumber', [function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attrs, controller) {

        controller.$formatters.push(function (modelValue) {
            var value = parseInt(modelValue, 10);
            return value;
        });

        controller.$parsers.push(function (viewValue) {
            var value = parseInt(viewValue, 10);
            return value;
        });          
    };
}]);

不过,虽然 $格式正在运行的每一次我在输入型的东西的时候,它没有覆盖输入字段的实际值,换句话说,它是没有任何剥离前导零。

But while the $formatter is being run every time I type something in the input, it is not overriding the actual value of the input field, in other words it is not stripping any leading zeros.

我可以通过监听DOM事件通过与

I can get this working by listening on DOM events (although I can't change the value on each keyup as that will move the cursor to the end of the field) by replacing the directive body with

element.on('focus', function() {
  var value = parseInt(element.val(), 10);
  if (value === 0)
    element.val('');
});

element.on('focusout', function() {
  if ('' === element.val().trim())
    element.val(0);
  else
    element.val(parseInt(element.val(), 10));
});

由此产生的行为是不够好(它清空了现场焦点,如果该值 0 及钢带领先 0 对事件的内容。

The resulting behaviour is good enough (it blanks out the field on focus if the value is 0 and strips leading 0s on focusout.

问题是,有没有我可以实现这种行为无需添加事件侦听器元素什么办法?如何正确控制输入如何使用渲染 ngModelController

Question is, is there any way I could have achieved this behaviour without adding event-listeners to element? How do I properly control how the input is rendered using ngModelController?

Plnkr: http://plnkr.co/edit/YOkFGNGamfA1Xb9pOP1U?p=preVIEW

推荐答案

所以,是的,寻找其他新的问题后,我看到了this并意识到我只是缺少控制器的调用。$渲染()

So, yeah, after looking at other new questions I saw this and realized I was simply missing a call to controller.$render()

controller.$parsers.push(function (viewValue) {
  var value = parseInt(viewValue, 10);
  controller.$viewValue = value;
  controller.$render();
  return value;
});

修正了我的问题。我现在就离开。

Fixes my problem. I'll go away now.