Как сэмулировать действие spin buttons?

287
18 марта 2017, 02:32

Здравствуйте!

Имеем примерно такой input:

<input  type="number"
    id="{{ variable.opt.name }}"
    name = "{{ variable.opt.name }}"
    min  = "{{ variable.opt.min }}"
    max  = "{{ variable.opt.max }}"
    step = "{{ variable.opt.step }}"
    ng-model = "variable.opt.value">

Подскажите пожалуйста, как можно сэмулировать действие "стрелочек вверх/вниз" у тега input[type="number"]

 

Мои действия:

Скрыл их с помощью CSS:

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
}
input[type='number'] {
  -moz-appearance: textfield;
}

Далее с помощью jQuery:

1. Подставляю свои стрелочки

setTimeout(function () {
    angular.element('input[type="number"]').each(function () {
        var t = jQuery(this);
        t.wrap('<div class="sb"></div>');
        t.before('<div class="sb-arrow sb-up"><i class="fl-up-arrow"></i></div>').after('<div class="sb-arrow sb-down"><i class="fl-down-arrow-2"></i></div>');
    });
}, 100);

2. Произвожу такие манипуляции (Ловлю нажатие на стрелочку и просто заменяю значение):

angular.element('body').on('click', '.sb-arrow', function () {
    var t = jQuery(this),
        input = t.parent().children('input'),
        step = (input.attr('step')) ? Number(input.attr('step')) : 1;
    if (t.hasClass('sb-up')) {
        input.val(Number(input.val()) + step);
        console.log('click');
    } else if (t.hasClass('sb-down')) {
        input.val(Number(input.val()) - step);
    }
});

И вроде бы как всё работает: циферки меняются.

НО! Изменения в модели не происходит :(

Попробовал так:

angular.element('body').on('click', '.sb-arrow', function () {
    var t = jQuery(this),
        input = t.parent().children('input'),
        step = (input.attr('step')) ? Number(input.attr('step')) : 1;
    if (t.hasClass('sb-up')) {
        var e = new jQuery.Event("keyup", { keyCode: 38 } );
        input.trigger(e)
    } else if (t.hasClass('sb-down')) {
        input.val(Number(input.val()) - step);
    }
});

Так вообще ничего не происходит.

Answer 1

Вся проблема в данном случае заключается в том, что при изменении значения поля ввода напрямую, ангуляр не знает, что что-то произошло и не обновляет значения соответствующих переменных.

Вместо использования jQuery, стоит написать свою директиву.

Задать ей сразу нужный шаблон, и передать в качестве параметра объект с настройками.

Директива может выглядеть так:

.directive('myInput',function(){
  return {
    restrict: 'E',
    scope:{
      options: '=' // указываем название параметра
    },
    template: `
    <div class="sb">
      <div class="sb-arrow sb-up" ng-click="up()">
        <i class="fl-up-arrow">^</i>
      </div>
      <input  type="number"
        id="{{ options.name }}"
        name = "{{ options.name }}"
        min  = "{{ options.min }}"
        max  = "{{ options.max }}"
        step = "{{ options.step }}"
        ng-model = "options.value">
      <div class="sb-arrow sb-down" ng-click="down()">
        <i class="fl-down-arrow-2">v</i>
      </div>
    </div>`,
    link: function(scope){
      // методы обработчики нажатия на кнопки. В них стоит добавить дополнительную логику проверки границ.
      scope.up = function(){ 
        scope.options.value += scope.options.step;
      };
      scope.down = function(){
        scope.options.value -= scope.options.step;
      }
    }
  };
});

Пример использования данной директивы:

angular.module('app', []) 
  .controller('ctrl', function($scope) { 
    $scope.variable = { 
      opt: { 
        min: 0, 
        max: 100, 
        step: 10, 
        value: 40, 
        name: 'sample' 
      } 
    }; 
  }) 
  .directive('myInput', function() { 
    return { 
      restrict: 'E', 
      scope: { 
        options: '=' // указываем название параметра 
      }, 
      template: ` 
        <div class="sb"> 
          <div class="sb-arrow sb-up" ng-click="up()"> 
            <i class="fl-up-arrow">^</i> 
          </div> 
 
          <input  type="number" 
            id="{{ options.name }}" 
            name = "{{ options.name }}" 
            min  = "{{ options.min }}" 
            max  = "{{ options.max }}" 
            step = "{{ options.step }}" 
            ng-model = "options.value"> 
 
          <div class="sb-arrow sb-down" ng-click="down()"> 
            <i class="fl-down-arrow-2">v</i> 
          </div> 
        </div>`, 
      link: function(scope) { 
        // методы обработчики нажатия на кнопки. В них стоит добавить дополнительную логику проверки границ. 
        scope.up = function() { 
          scope.options.value += scope.options.step; 
        }; 
        scope.down = function() { 
          scope.options.value -= scope.options.step; 
        } 
      } 
    }; 
  });
<script data-require="angular.js@1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script> 
<div ng-app="app" ng-controller="ctrl"> 
  <my-input options="variable.opt"></my-input> 
  <pre> 
{{variable|json}} 
  </pre> 
</div>

READ ALSO
Не обновляется captcha

Не обновляется captcha

Капча работает, но при нажатие обновить она не обновляется, лишь при перезагрузки страницы Вот блок с капчей

348
Получение индекса объекта в массиве

Получение индекса объекта в массиве

Всем привет! Нужно не столько решение, сколько подсказкаКак получить индекс объекта в массиве типа - [1, 2, 3, 4] - понятно

257
Как изменить HTML внутри div span span на чистом JavaScript

Как изменить HTML внутри div span span на чистом JavaScript

Всем приветКак изменить HTML внутри div span span на чистом JavaScript? делаю пока так

300
Как построить дерево ссылок на javascript?

Как построить дерево ссылок на javascript?

Подскажите пожалуйста как на javascript реализовать дерево ссылокНапример есть такой массив

348