2015-08-13 2 views
0

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

В приведенном ниже коде у меня есть ввод времени, в котором пользователь может ввести строку, представляющую время («00:00»), директиву вычисляет фактическое значение и устанавливает его соответственно каждый раз, когда пользователь меняет строковое значение.

Однако, поскольку фактическое значение выставлено и может быть изменено другим компонентом, мне нужно каким-то образом сделать строковое значение согласованным с фактическим значением.

$ watch - это одно решение, но тогда мне нужно отключить часы, когда в методе onChange(). Поэтому мне интересно, есть ли лучший способ сделать это.

[EDIT]: Причина, по которой я использую ng-blur, связана с проверкой в ​​случае, если строковое значение не является допустимым форматом, оно возвращается обратно к фактическому значению.

Приветствия,

Jsfiddle: https://jsfiddle.net/minhnq013/v5rax0vk/3/

angular.module('myapp', []) 
    .directive('timeInput', function() { 
    return { 
     restrict: 'E', 
     template: '<input type="text" ng-model="ctrl.strValue" ng-blur="ctrl.onChange()"/><span ng-bind="ctrl.value"></span>', 
     scope: { 
      'value': '=' 
     }, 
     controller: Controller, 
     controllerAs: 'ctrl', 
     bindToController: true 
    }; 

    function Controller() { 
     var ctrl = this; 
     ctrl.value = ctrl.value || 0; 
     ctrl.strValue = "00:00"; 

     /** 
     * Called when the UI determine user input value has change, 
     * Set the internal value to be same as user input text value. 
     **/ 
     function onChange() { 
      var hour = ctrl.strValue.substr(0, 2); 
      var minute = ctrl.strValue.substr(3); 
      var dateObj = new Date(ctrl.value); 
      var regex = new RegExp("^\\d{2}:\\d{2}$"); 
      // If format is not valid, revert to last value 
      if (!ctrl.strValue.match(regex)) { 
       ctrl.strValue = ("0"+dateObj.getUTCHours()).slice(-2) + ":" + ("0"+dateObj.getUTCMinutes()).slice(-2); 
       return; 
      } 

      dateObj.setUTCHours(hour); 
      dateObj.setUTCMinutes(minute); 
      ctrl.value = dateObj.getTime(); 
     } 
     ctrl.onChange = onChange; 

     function filterText() { 

     } 
    } 
}); 

ответ

0

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

Фильтр будет отвечать за отображение отформатированных внутренних данных. Это устраняет необходимость хранения двух объектов по существу одного значения.

Кроме того, использование фильтра устранит необходимость в событиях onChange.

Для получения дополнительной информации о фильтрах см: https://scotch.io/tutorials/building-custom-angularjs-filters

+0

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

+0

@MikeNQ, каковы текущие внутренние и отображаемые форматы? –

+0

Это как в jsfiddle, формат String - «hh: mm» для представления времени. Хотя фактическое значение представляет собой миллисекунду целочисленного значения в формате UTC. – MikeNQ

0

Там много различных способов структурировать, но я хотел бы предложить, что вместо того, чтобы использовать часы, вы пытаетесь сохранить его событийным. Я частично основываю это на вашем комментарии к коду, чем ваш вопрос Called when the UI determine user input value has change, но похоже, что вы можете просто подумать о неправильном событии для того, чего вы пытаетесь достичь. Как насчет того, чтобы сменить ng-blur на что-то вроде ng-change, чтобы вы выполняли функции при каждом изменении, чтобы синхронизировать вашу логику. Вы можете легко соединить это с параметрами модели для некоторой довольно удивительной функциональности, например, если вы хотите, чтобы замедлить его до половины второго обновления как: ng-model-options="{ debounce: { 'default': 500 } }"

template: '<input type="text" ng-model="ctrl.strValue" ng-change="ctrl.onChange()"/><span ng-bind="ctrl.value"></span>', 
+0

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

+0

. Это плохо для того, чтобы не включать причину использования ng-change. Существует также механизм проверки подлинности, который возвращает значение строки к фактическому значению, если формат строки недействителен. Но это лучше всего проверять после того, как пользователь отключит фокус. – MikeNQ

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