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


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

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

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

// 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'}}

есть ли ярлык, который я упускаю?

6 73

6 ответов:

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

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

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 пример.

наличие разных значений в вашем поле ввода и в вашей модели противоречит самой природе 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'};

});

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

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

вместо того, чтобы писать новую директиву просто НЕ ИСПОЛЬЗОВАТЬ the 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'}}" /> 

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

полный пример, который форматирует числа, вставляя пробелы каждые 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, ' ').reverse()
    modelCtrl.$parsers.push (input) ->
      return unless input?
      input.replace(/\s/g, '')

использование:

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

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

угловой имеет встроенный дата в формате функциональность, но чтобы применить ее к входу, где вы в конечном итоге хотите получить необработанную (неформатированную) дату, вам нужно создать пользовательский директива.

Пример Директивы:

(function () {
    'use strict';

    angular.module('myApp').directive('utcDate', ['$filter', function ($filter) {
        return {
            restrict: 'A', //restricting to (A)ttributes
            require: 'ngModel',
            link: function (scope, elem, attrs, model) {
                if (!model) return;

                var format = 'MM/dd/yyyy h:mm:ss a';
                var timezone = 'UTC';

                //format the date for display
                model.$formatters.push(function (value) {
                    //using built-in date filter
                    return $filter('date')(value, format, timezone);
                });

                //remove formatting to get raw date value
                model.$parsers.push(function (value) {
                    var date = Date.parse(value);
                    return !isNaN(date) ? new Date(date) : undefined;
                });
            }
        };
    }]);
})();

затем применить его:

<input type="text" ng-model="$ctrl.DateField" utc-date />

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

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