Directive for AngularJS Input with interactive buttons

I am currently developing a custom directive that will show a set of buttons for incrementing or decrementing the value in an input field when it is in focus. The buttons represent Imperial units such as 1/8", 1/4", and 1/2".

The primary issue I'm facing is that when a button is clicked, the input field loses focus causing the buttons to disappear as per the directive.

Another challenge I'm encountering is figuring out how to access the ngModel to correctly update the input value based on the button pressed. Although I placed the directive around the input for layout purposes, I'm open to suggestions on how to streamline this process by directly tying it to the input element.

Below is my current code setup:

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 implementation:

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){

                    };
                }
            }
        }]);

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 experimenting with the loss of focus issue, I found a workaround by modifying the 'blur' event as shown below. This solution works, but I'm open to better alternatives:

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

Answer №1

Check out this improved version to get the directive working.

Here are some solutions to your issues:

  1. To handle losing focus, compare event.targetElement with the buttons in your template.
  2. Add value using ngModelCtrl.$setViewValue (obtained by using require).
One suggestion: I recommend not using transclusion, but rather applying the directive directly to the input element itself.

If you need more assistance, feel free to reach out.

UPDATE

How can this be done without transclusion?

The simplest way is to use something like this method, or dynamically (see: HERE). Essentially, you can utilize the $compile service to manually add the buttons' panel to the DOM.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An unexpected error has occurred in the browser console: The character '@' is not valid

I recently made the decision to dive into learning about Unit Testing with JavaScript. To aid in this process, I started using both Mocha.js and Chai.js frameworks. I downloaded the latest versions of these frameworks onto my index.html from cdnjs.com. How ...

Clicking the submit button in JavaScript will trigger a request to the Spring MVC backend,

When I use the following code, it gives me an object response: @RequestMapping(value = "/NewLogin",method = RequestMethod.POST) public @ResponseBody Token getAllBooks( Token token = new Token(); token.setValue(encryptedMessage); return toke ...

Using JavaScript to delete the initial option from a dropdown menu

Below is the code snippet: <select id="List" name="UserType" onChange ="hide"> <option value="0" disabled="disabled" selected="selected">User Type</option> <option value="1" onclick="hide">Administrator</option> ...

Determine total and showcase it as the range slider is adjusted

Seeking to calculate and present the result of three range sliders. The equation I aim to showcase is: KM driven per year * Avg KM/100L / Price of fuel I have managed to display each slider's individual values, but I am uncertain about how to show t ...

Problems arising from the usage of setInterval within the useEffect hook

I have encountered an issue while trying to use setInterval within useEffect. To ensure functionality, I moved the logic to a separate function and it works perfectly; alternating between two images every 3 seconds as intended. const rotateImages = (img) ...

"Utilizing Vue Mixins on a global scale, but restricting their usage to local components

Is there a way to use a mixin in multiple components without having to constantly import and declare it? I've tried connecting the mixin object to a global variable using vue.prototype, but mixins are added to components before globals are accessible. ...

Strategies for dynamically altering Vue component props using JavaScript

for instance: <body> <div id="app"> <ro-weview id="wv" src="http://google.com"></ro-weview> </div> <script> (function () { Vue.component("ro-webview", { props: ["src"], template: ` <input type="t ...

Concealing functions within Accessors

I've recently started working on a website project utilizing the node.js/express stack and I am experimenting with developing in the functional programming style, which is quite new to me. One issue I encountered was related to the express method res. ...

error message: "The mtlLoader Module does not have the export named 'MTLLoader'"

I am struggling with getting the mtlLoader module to work in three.js. I am a beginner and I am trying to import the mtlLoader module from the latest three.js-master repository on the official website. However, I keep encountering this error message when I ...

"Unfortunately, the JavaScript external function failed to function properly, but miraculously the inline function

Struggling to create a fullscreen image modal on the web? I was able to get it working fine when embedding the script directly into my HTML file, but as soon as I moved it to an external JS file, things fell apart. I've double-checked all the variable ...

Using setInterval() does not automatically fetch JSON data at a specified interval for me

Attempting to constantly update the latitude and longitude coordinates from a dynamic API has proven to be a challenge. Despite utilizing jQuery with a set interval of 1000 milliseconds, the data retrieval from the API does not occur as expected. While i ...

Authenticate through navigation on an alternate component

I am in the process of developing a user interface that includes a side navigation and header bar. However, if the user is not logged in, I wish to redirect them to the login page. The primary component structure is as follows: class App extends Componen ...

Leveraging websockets in AngularJS to display the total count of alerts

I have an API that returns the total number of alerts. I want to implement a web socket for real-time updating in the header (similar to Facebook notifications) whenever the number is greater than zero. Currently, I am using Restangular to make API calls ...

In the world of node.js, functions almost always have a tendency to

As a beginner in the world of nodejs, I am diving into various guides and screencasts to grasp the basics. One aspect that has caught my attention is the handling of async/sync operations, reading files, and understanding how nodejs deals with callbacks/re ...

Ways to address the issue of "$ is not a function"

Whenever I attempt to upload an image, this error message pops up: $ is not a function The source of the error can be found here: $(document).height(); ...

Error: Attempting to access 'position' property of undefined object in ThreeJs is causing a TypeError

I am currently facing an issue with integrating a 3D model into the background of the hero section on my website. The integration works fine, but I noticed that when I manually resize the window, the 3D model does not adjust to the new size. Additionally, ...

Using TypeScript and webpack 2 to integrate typeahead.js into your project

I am encountering an error message coming from webpack. ERROR in ./wwwroot/js/admin/infrastructure/typeaheadComponent.ts Module not found: Error: Can't resolve 'typeahead' in ... I have the following dependencies installed npm install ...

Creating a visual representation of a JSON tree using nested <ul> elements in AngularJS

Consider a JSON tree structure like the one shown below: var myTree = { "node": { "name": "A", }, "children": [ { "node": { "name": "B", }, "children": [] }, { "node": { "name": "C", }, ...

What is the method for modifying a button's shape in Material UI by utilizing the theme?

After going through the documentation for the Button component, I noticed that it has various sections and even a Codesandbox available at this link However, there is no mention of how to change the shape of a button if necessary. https://i.sstatic.net/T ...

"Struggling with setting the default checked state for single and multiple checkboxes? The ng-init method with checkboxModel.value=true seems to be ineffective – any suggestions

<input type="checkbox" ng-model="isChecked.value" ng-true-value="'yes'" ng-false-value="'no'" ng-click='handleCheckboxChange(isChecked.value, idx);' ng-init="isChecked.value=true" /> ...