Brian
Brian

Reputation: 2305

AngularJS Input Directive with buttons

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

Upvotes: 1

Views: 1114

Answers (1)

artur grzesiak
artur grzesiak

Reputation: 20348

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.

Upvotes: 1

Related Questions