Como criar um tipo de input personalizado?

Eu gostaria de criar um tipo de input personalizado semelhante ao modo como o AngularJS implementa “email”, por exemplo.

 

O que eu gostaria de criar é um tipo de input como este:

  

Alguma idéia de como isso pode ser feito? Até agora, só consegui descobrir como implementar diretivas personalizadas onde ‘path’ é o nome da tag, atributo ou class.

Por exemplo, posso fazer com que isso funcione, mas é inconsistente com os outros campos do formulário e eu realmente gostaria que eles parecessem iguais.

  
 app.directive('path', function() { return { require: 'ngModel', link: function(scope, elm, attrs, ctrl) { ... } }; }); 

Você pode criar seu próprio tipo de input = “caminho” criando uma diretiva de input com lógica customizada se o atributo type estiver definido como “caminho”.

Eu criei um exemplo simples que simplesmente substitui \ por / . A diretiva é assim:

 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); }); }); } }; }); 

Exemplo

Atualização : Alterado, off para bind , unbind para remover a dependência do jQuery. Exemplo atualizado.

Uma solução alternativa pode ser obtida usando a propriedade $parsers do ngModelController . Esta propriedade representa uma cadeia de analisadores que são aplicados ao valor do componente de input antes de passá-los para validação (e, eventualmente, atribuí-los ao modelo). Com isso, a solução pode ser escrita como:

 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, '/'); }); } }; }); 

Note que há outra propriedade $formatters que é um pipeline de formatadores que transformam um valor de modelo no valor exibido na input.

Veja aqui para o plunker.

Considerando que a function de compilation é a primeira da fila, não seria melhor com:

 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); }); }); } } }; });