Как создать собственный тип ввода?
Я хотел бы создать пользовательский тип ввода, похожий на способ, которым, например, 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) { ... }
};
});
Ответы
Ответ 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);
});
});
}
}
};
});