Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am working to create a directive which will, on focus of an input field, display a set of buttons used to increment or decrement the value in the input. In this case Imperial units (1/8",1/4",1/2").

The first issue I am running into is that when a button is pressed, the focus comes off of the input and so the buttons are hidden via the directive.

The second issue is I am unsure of exactly how to access the ngModel in order to properly add (or remove) the value of the button pressed. The main reason for having the directive around the input instead of directly on the input is for formatting where I want the buttons to be placed but if that can be done when tied to the input that would certainly make this directive significantly less hard to make work correctly.

Here is the code I have setup thus far:

Form input:

 <measurements>
    <label>
      <span>Length</span>
      <i ng-show="form.length.$dirty && form.length.$error.required" class="error-icon"></i>
      <input type="number" name="length" ng-model="form.length" required placeholder="Length">
    </label>
  </measurements>

The directive currently:

angular.module('directive.measurements', [])
    .directive('measurements', [function() {
            return {
                restrict: 'EA',
                transclude: true, 
                templateUrl: 'measurements.html',
                scope: {
                },
                link: function(scope, element, attrs, ctrls) {
                    scope.focused = false;
                    var input = element.find('input');
                    input.on('focus', function(event) {
                        scope.focused = true;
                        scope.$apply();
                    });
                    input.on('blur', function(event) {
                        scope.focused = false;
                        scope.$apply();
                    });
                    scope.add = function(amt){

                    };
                }
            }
        }]);

Finally the template 'measurements.html':

<div>
  <span ng-show="focused">
    <button class="button button-small" ng-click="add(.125)">+1/8</button>
    <button class="button button-small" ng-click="add(.25)">+1/4</button> 
    <button class="button button-small" ng-click="add(.5)">+1/2</button>
  </span>
  <span ng-transclude>
  </span>
</div>

EDIT After playing around a little bit with the focusing issue I came up with changing the 'blur' event to the following, whether this is best or not I am not sure, but it does work:

if (event.relatedTarget === null) {
  input[0].focus();
} else {
  scope.focused = false;
  scope.$apply();
}

Edit 2 Here is the plunker: http://plnkr.co/edit/6eUgRhUSA8yI1s42j9JD?p=preview

share|improve this question
    
can you create a demo plunker or jsfiddle for us to play with? –  Beyers Apr 11 at 14:52
    
Added plunker example –  Brian Apr 11 at 15:19
    
It looks like your directive depends on the <input> tag inside your <measurement> tags. Why not include the <input> tag directly in the directive's template? Why nest other content within the directive? The directive should be self-reliant. –  Tyler Eich Apr 11 at 15:44
add comment

1 Answer

up vote 1 down vote accepted
+50

HERE is an improvement of your plnkr to make the directive working.

Regarding your issues:

  1. Losing focus is handled by comparing event.targetElement with buttons from your template.
  2. Adding value is achieved with ngModelCtrl.$setViewValue (ngModelCtrl is obtained with require).
small comment

I would not use transclusion at all -- instead would use the directive directly on the input element itself.

Give me a shout if more help needed.

UPDATE

How could this be achieved without transclusion?

In the most straightforward way you can use something like THAT or do it dynamically (look: HERE). Basically you make use of $compile service to manually add the buttons' panel to DOM.

share|improve this answer
    
How could this be achieved without transclusion? I was thinking about avoiding it but couldn't figure out how to add/remove the buttons? This is a more contrived example of my actual code, which is a page full of these with other validation items as well. –  Brian Apr 11 at 16:06
    
Ooohh yea i just figured with so many on the page the compile of all of those would slow the page down quite a bit, but that would certainly encapsulate it quite nicely. –  Brian Apr 11 at 17:01
    
Thought about the performance and therefore proposed the dynamic compilation. For sure, it will be faster than your initial approach with transclusion. –  artur grzesiak Apr 11 at 17:03
    
Scratch my last comment didn't know what you meant by dynamically until i read the second plunkr code. Thanks for the help! –  Brian Apr 11 at 17:03
    
Great, glad that could help :-) –  artur grzesiak Apr 11 at 17:04
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.