1

I have a single box.width ng-model value within a form, intending to store the box's width in inches. I'd like users to be able to see the width in "ft" and "in", though. For the most part, I have it working. I have 2 directives doing the work of formatting the total # of inches into the # of feet and the # of remaining inches.

Example: http://plnkr.co/edit/Zar1vQ7L2NlxyZeBmY4n?p=preview

Problem:

The parser that's triggered when a user modifies the # of inches in the form only works somewhat reliably. If the user repeatedly clicks the up-tick arrow, the inches field will sometimes stay at 11 (as a maximum value, as desired), but will sometimes allow a 12 to be entered. Judging from the console logs, it's like the parser's not even getting fired some of the time (perhaps due to how I'm setting element.val() in the parser). Here's the relevant parser function:

function inchesOnlyParser(input) {
   var numFeet = Math.floor(ngModelController.$modelValue / 12);
   var inchesEntered = input;

   if (inchesEntered > 11) {
       var small = numFeet * 12 + 11;
       element.val(11);
       return small;
   }

   return numFeet * 12 + inchesEntered;
}

At first I tried putting max=11 on the input field for the inches breakdown, but that causes angular to put a maximum value on the total number of inches, so isn't a solution for me.

I've tried working with the various ngModelController methods mentioned at https://docs.angularjs.org/api/ng/type/ngModel.NgModelController but haven't found a solution that works for me, including a combination of $rollbackViewValue, $render, $setViewValue, etc. I may just not be understanding the documentation quite right, though.

As I've hinted at, my desired UI would be that the user wouldn't be able to exceed 11 inches within the inches input field; it'd act similar to the max=11 setting if Angular weren't involved.

jmq
  • 2,359
  • 18
  • 32

1 Answers1

0

Inside your inchesOnly directive, instead of setting input element's value using element.val(11);, set the view value and render it again.

ngModelController.$setViewValue(11);
ngModelController.$render(); 

Related SO question https://stackoverflow.com/a/19168292/1061668

Community
  • 1
  • 1
Mikko Viitala
  • 8,344
  • 4
  • 37
  • 62
  • That makes perfect sense. The docs say **"It is expected that the user of the ng-model directive will implement this method."** So I was trying to write `ngModelController.$render = function() {...}` but it looks like I was mistaken in that being necessary. However, reviewing your suggestion and the example at the bottom of the [docs](https://docs.angularjs.org/api/ng/type/ngModel.NgModelController), it would also work if I had implemented what you suggested along with `ngModelController.$render = function() { element.val(ngModelController.$viewValue); }` Thanks! – jmq Jan 26 '15 at 18:40