Как создать собственный тип ввода? - программирование
Подтвердить что ты не робот

Как создать собственный тип ввода?

Я хотел бы создать пользовательский тип ввода, похожий на способ, которым, например, AngularJS реализует "электронную почту".

<input type="email" ng-model="user.email" />

То, что я хотел бы создать, - это тип ввода, подобный этому:

<input type="path" ng-model="page.path" />

Любые идеи о том, как это можно сделать? До сих пор мне удалось выяснить, как реализовать пользовательские директивы, где "путь" - это имя тега, атрибута или класса.

Например, я могу заставить это работать, но он несовместим с другими полями формы, и мне бы очень хотелось, чтобы они выглядели одинаково.

<input type="text" ng-model="page.path" path />
app.directive('path', function() {
  return {
    require: 'ngModel',
    link: function(scope, elm, attrs, ctrl) { ... }
  };
});
4b9b3361

Ответ 1

Вы можете создать свой собственный тип ввода = "путь", создав директиву ввода с пользовательской логикой, если атрибут type установлен в "путь".

Я создал простой пример, который просто заменяет \ на /. Директива выглядит так:

module.directive('input', function() {
    return {
        restrict: 'E',
        require: 'ngModel',
        link: function (scope, element, attr, ngModel) {
          if (attr.type !== 'path') return;

          // Override the input event and add custom 'path' logic
          element.unbind('input');
          element.bind('input', function () {
            var path = this.value.replace(/\\/g, '/');

            scope.$apply(function () {
              ngModel.$setViewValue(path);
            });
          });
        }
    };
});

Пример

Обновить: изменено on, off на bind, unbind, чтобы удалить зависимость jQuery. Пример обновлен.

Ответ 2

Альтернативное решение может быть достигнуто с помощью свойства $parsers ngModelController. Это свойство представляет цепочку парсеров, которые применяются к значению входного компонента, прежде чем передавать их на проверку (и в конечном итоге назначить их модели). При этом решение может быть записано как:

module.directive('input', function() {
    return {
        restrict: 'E',
        require: 'ngModel',
        link: function (scope, element, attr, ngModel) {
          if (attr.type !== 'path') return;

          ngModel.$parsers.push(function(v) {
            return v.replace(/\\/g, '/');
          });
        }
    };
});

Обратите внимание, что существует другое свойство $formatters, которое является конвейером форматировщиков, которые преобразуют значение модели в значение, отображаемое на входе.

Смотрите здесь для плункера.

Ответ 3

Учитывая, что функция компиляции является первой в строке, было бы не лучше:

module.directive('input', function() {
  return {
    restrict: 'E',
    require: 'ngModel',
    compile: function Compile(tElement, tAttrs) {
      if (tAttrs.type !== 'path') return;

      return function PostLink(scope, element, attr, ngModel) {
        // Override the input event and add custom 'path' logic
        element.unbind('input');
        element.bind('input', function () {
          var path = this.value.replace(/\\/g, '/');

          scope.$apply(function () {
            ngModel.$setViewValue(path);
          });
        });
      }
    }
  };
});