Использование углового фильтра в входном элементе

Надеюсь, что я не пропустил ничего очевидного в doco, если у меня есть, я уверен, что кто-то поможет.

Я использую asp.net webapi для возврата DTO с полями даты. Они сериализуются с использованием JSON.Net(в формате "2013-03-11T12: 37: 38,693" ).

Я хотел бы использовать фильтр, но в элементе INPUT, возможно ли это или я должен создать новый фильтр или директиву для выполнения этого?

// this just displays the text value
<input ui-datetime type="text" data-ng-model="entity.date" /> 
// this doesn't work at all
<input ui-datetime type="text" data-ng-model="{{entity.date|date:'dd/MM/yyyy HH:mm:ss a'}}" /> 
// this works fine
{{entity.date|date:'dd/MM/yyyy HH:mm:ss a'}}

Есть ли какой-либо ярлык, который мне не хватает?

Ответ 1

Вкратце: если вы хотите, чтобы ваши данные имели другое представление в представлении и в модели, вам понадобится директива, которую вы можете представить как двухстороннюю фильтр.

Ваша директива будет выглядеть примерно так:

angular.module('myApp').directive('myDirective', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModelController) {
      ngModelController.$parsers.push(function(data) {
        //convert data from view format to model format
        return data; //converted
      });

      ngModelController.$formatters.push(function(data) {
        //convert data from model format to view format
        return data; //converted
      });
    }
  }
});

HTML:

<input my-directive type="text" data-ng-model="entity.date" /> 

Вот пример работы jsFiddle.

Ответ 2

Наличие разных значений в вашем поле ввода и в вашей модели идет вразрез с самой природой ng-модели. Поэтому я предлагаю вам простейший подход и применить свой фильтр внутри контроллера, используя отдельную переменную для отформатированной даты и использовать наблюдателей для синхронизации отформатированных и исходных дат:

HTML:

<input ui-datetime type="text" data-ng-model="formattedDate" />

JS:

app.controller('AppController', function($scope, $filter){

  $scope.$watch('entity.date', function(unformattedDate){
    $scope.formattedDate = $filter('date')(unformattedDate, 'dd/MM/yyyy HH:mm:ss a');
  });

  $scope.$watch('formattedDate', function(formattedDate){
    $scope.entity.date = $filter('date')(formattedDate, 'yyy/MM/dd');
  });

  $scope.entity = {date: '2012/12/28'};

});

Ответ 3

Если на вашем входе отображаются только данные

Если вам действительно нужен ввод для просто отображения некоторой информации, и это другой элемент, который изменяет модель Angular, вы можете сделать более легкое изменение.

Вместо написания новой директивы просто НЕ ИСПОЛЬЗУЙТЕ ng-model и используйте хороший старый value.

Итак, вместо:

<input data-ng-model={{entity.date|date:'dd/MM/yyyy HH:mm:ss'}}" /> 

Это сделает:

<input value="{{entity.date|date:'dd/MM/yyyy HH:mm:ss'}}" /> 

И работает как шарм:)

Ответ 4

Полный пример, который форматирует числа, вставляя пробелы каждые 3 символа, начиная с конца:

'use strict'
String::reverse = ->
  @split('').reverse().join('')

app = angular.module('app', [])
app.directive 'intersperse', ->
  require: 'ngModel'
  link: (scope, element, attrs, modelCtrl) ->
    modelCtrl.$formatters.push (input) ->
      return unless input?
      input = input.toString()
      input.reverse().replace(/(.{3})/g, '$1 ').reverse()
    modelCtrl.$parsers.push (input) ->
      return unless input?
      input.replace(/\s/g, '')

Применение:

<input ng-model="price" intersperse/>

Пример Plunkr: http://plnkr.co/edit/qo0h9z

Ответ 5

Вам не нужно будет создавать новый фильтр с нуля, так как angular уже имеет встроенный фильтр для типов дат. http://docs.angularjs.org/api/ng.filter:date

Я считаю, что именно то, что вам нужно.