2013-09-12 4 views
12

я хочу сделать следующее:AngularJs - Директива для изменения входного форматирования

У меня есть объект даты в моей модели контроллера, и я хочу, чтобы позволить пользователю изменить его. Пользователю должны быть предоставлены два поля ввода. Первое поле ввода должно изменить дату, а другое - время. Оба поля ввода должны работать с той же моделью даты.

<input ng-model="model.date" date-format="YYYY-MM-DD"> 
<input ng-model="model.date" date-format="HH:mm:SS"> 

Я не нашел литературы об этой привязке. Обычно директива ng-model заботится о значении поля ввода. Теперь я хочу переписать это значение с помощью собственного форматирования. Кроме того, если пользователь меняет ввод, изменения должны быть проанализированы и помещены обратно в объект даты.

Поскольку манипуляция с датами в vanilla js является довольно странной, я использовал moment.js для форматирования и анализа дат и строк.

Мой текущий подход выглядит следующим образом:

app.directive('dateFormat', function() { 
    return { 
     restrict: 'A', 
     link: function(scope, el, at) { 
      var format = at.dateFormat; 
      scope.$watch(at.ngModel, function(date) { 
       var result = moment(date).format(format); 
       el.val(result); 
      }); 
     } 
    }; 
}); 

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

Мои вопросы:

  • Как я могу смоделировать это?
  • Является ли этот подход действительным с угловой философией или я делаю что-то странное здесь?
  • Могу ли я использовать ng-модель и мою директиву формата даты?
  • Есть ли более простой способ сделать это?
+0

Итак, вы когда-нибудь найти хорошее решение для этого? :) Я вхожу в аналогичную позицию, где я хочу сохранить свойство модели как объект Date, но все же разрешить пользователю редактировать его в поле редактирования с примененной маской даты. –

ответ

15

Фильтр является то, что вы ищете:

//In your controller 
$scope.modelDate = $filter('date')(dateToFormat, "YYYY-MM-DD"); 

//In your view 
<input ng-model="modelDate" type="text"> 

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

Так что для вашего кода, было бы что-то вроде этого:

return { 
    require: 'ngModel', 
    link: function(scope, element, attrs, ngModelController) { 
    ngModelController.$parsers.push(function(data) { 
     //View -> Model 
     return data; 
    }); 
    ngModelController.$formatters.push(function(data) { 
     //Model -> View 
     return $filter('date')(data, "YYYY-MM-DD"); 
    }); 
    } 
} 

Более подробная информация here

3

У меня была такая же проблема, и после некоторых исследований и испытаний, я придумал следующее решение. Он выполняет требуемое форматирование и проверку на «размытие» не во время каждого нажатия клавиши. Посмотрите на теги комментариев для информации на каждом шаге. Для выполнения валидации дат вам понадобится moment.js.

myApp.directive('validDate', function ($filter, $window, $parse, $timeout) { 
return { 
    require: '?ngModel', 
    restrict: 'A', 
    compile: function() { 
     var moment = $window.moment; 
     var getter, setter; 
     return function (scope, element, attrs, ngModel) { 
      //Declaring the getter and setter 
      getter = $parse(attrs.ngModel); 
      setter = getter.assign; 
      //Set the initial value to the View and the Model 
      ngModel.$formatters.unshift(function (modelValue) { 
       if (!modelValue) return ""; 
       var retVal = $filter('date')(modelValue, "MM/dd/yyyy"); 
       setter(scope, retVal); 
       console.log('Set initial View/Model value from: ' + modelValue + ' to ' + retVal); 
       return retVal; 
      }); 

      // If the ngModel directive is used, then set the initial value and keep it in sync 
      if (ngModel) { 
       element.on('blur', function (event) { 
        var date = moment($filter('date')(element.val(), "MM/dd/yyyy")); 
        // if the date entered is a valid date then save the value 
        if (date && moment(element.val(), "MM/DD/YYYY").isValid() && date <= moment() && date >= moment("01/01/1900")) { 
         element.css('background', 'white'); 
         element[0].value = $filter('date')(date.toDate(), "MM/dd/yyyy"); 
         console.log('change value to ' + element.val()); 
         var newValue = element.val(); 
         scope.$apply(function() { 
          setter(scope, newValue); 
         }); 
        } else { //show an error and clear the value 
         console.log('INCORRECT VALUE ENTERED'); 
         element.css('background', 'pink'); 
         element[0].value = ""; 
         scope.$apply(function() { 
          setter(scope, ''); 
         }); 
        } 
       }); 
      } 
     }; 
     } 
    }; }); 

И директива может использоваться в представлении, как следующее:

<input type="text" ng-model="member.BirthDate" required valid-date /> 
+1

Извините, но с помощью 'ngModel. $ Formatters', а затем проверки' if (ngModel) 'не имеет смысла. –

Смежные вопросы