I'm having trouble with my AngularJS Spinner directive

Check out this simple directive I created to display a spinner on my button while something is happening remotely: http://plnkr.co/edit/rAJ4X7A3iidmqUD2M63A?p=preview

Here's the html:

<!DOCTYPE html>
<html ng-app="app">

    <head>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
        <script src="script.js"></script>
    </head>

    <body ng-controller="myController as vm">

        <button ng-click="vm.saveAction()" class="btn btn-primary" type="button">
            <!-- Original template -->

            <i class="fa fa-floppy-o" ng-hide="vm.save"></i>
            <i class="fa fa-circle-o-notch fa-spin ng-hide" ng-show="vm.save"></i> Save

            <!-- end -->
        </button>

        <button ng-click="vm.removeAction()" class="btn btn-default" type="button">
            <!-- Desired template (directive) -->

            <i my-spinner="vm.remove" icon="fa fa-trash"></i> Remove

            <!-- end -->
        </button>

    </body>

</html>

And here's the JavaScript:

app = angular.module('app', []);

app.controller('myController', ['$timeout', function($timeout) {
    var vm = this;

    vm.save = false;
    vm.remove = false;

    vm.saveAction = function() {
              vm.save = true;

              // ...save something remote

              $timeout(function() { // <-- simulate an async callback or whatever...
                vm.save = false;
              }, 3000);
    };

      vm.removeAction = function() {
              vm.remove = true;

              // ...remove something remote

              $timeout(function() { // <-- simulate an async callback or whatever...
                  vm.remove = false;
              }, 3000);
    };
}]);

app.directive('mySpinner', function() {
    var directive = {
        restrict: 'A',
        scope: {
            mySpinner: '@',
            icon: '@'
        },
        template: '<i class="{{icon}}" ng-hide="{{mySpinner}}"></i>' +
                  '<i class="fa fa-circle-o-notch fa-spin ng-hide" ng-show="{{mySpinner}}"></i>',
    };

    return directive;
});

I chose to use ng-show and ng-hide in my solution so that I don't have to $observe/$watch anything in my directive... Everything seems correct in the directive, but when I click on the Remove button, nothing happens. Can anyone help me troubleshoot this issue? Thank you!

Answer №1

Instead of using @(one way binding) to pass the value of mySpinner, you should use =(two way binding). When you use @, the value is passed through an attribute with interpolation {{}} directive, which converts the boolean to a string and always evaluates the expression in ng-show as true.

Another reason it wasn't working is because you were using {{}} interpolation inside the ng-show and ng-hide directives.

Directive

app.directive('mySpinner', function() {
  var directive = {
    restrict: 'A',
    scope: {
      mySpinner: '=',
      icon: '@'
    },
    template: '<i class="{{icon}}" ng-hide="mySpinner"></i>' +
      '<i class="fa fa-circle-o-notch fa-spin ng-hide" ng-show="mySpinner"></i>',
  };
  return directive;
});

You can refactor your template to use ng-class instead of using ng-show and ng-hide by applying classes conditionally.

template: '<i ng-class="mySpinner ? \'fa fa-circle-o-notch fa-spin=\': icon"></i>'

Update PLunkr

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

Having trouble with PHP's JSON encoding functionality?

Take a look at my code for validating with angular and php. I need to check the validity of this form <form ng-submit="dk()"> <label for="">Name</label> <input type="text" name="name" ng-model="formData.name"> {{errorName}} &l ...

Exploring intricate designs using HTML and Javascript

After extensive experience with both WPF and HTML5 JavaScript, one thing that stands out to me is the clear organization provided by XAML's defined panels. Grid, StackPanel, DockPanel, WrapPanel, and others offer a straightforward way to achieve consi ...

JavaScript document string separation

Hi there, I'm a newbie here and could really use some assistance. I am struggling with creating a function and would appreciate any ideas... To give you an idea of what I need help with, I have a String and I want to check if it contains a specific w ...

Cannot chain promises using 'then'

Having trouble understanding why the 'describeDir' promise chain is not working properly. Can anyone help me figure out what I did wrong here? Everything in the code seems to run, but functions like then or finally from the promise API never get ...

"Streamlining data entry with an uncomplicated HTML form input that accepts multiple values from a

As I understand it, a barcode scanner functions as nothing more than a keyboard that transmits keycode 13 after each scan. My task is straightforward: I have a basic form with only one input field and I want the ability to scan numerous barcodes and then c ...

Print directly without the need for a preview or dialog box

Is there a way to easily print content with just one click, without having to go through the preview or print dialog box? Here is a snippet of my code: <head> <style type="text/css"> #printable { display: none; } @media print { #non-pr ...

Enhancing the visual appeal of a standard jQuery slider with thumbnails

Recently, I incorporated the Basic jQuery slider into my website, which can be found at . As a novice in jQuery but well-versed in HTML and CSS, I have managed to make it work seamlessly on my site. However, I am curious to know if there is a way to displa ...

Shared Vue configuration settings carrying over to Jest spec files

For my unit testing of components using VueJS and Jest, I'm incorporating the Bootstrap Vue library for styling. To address console warnings regarding unknown plugins, I've set up a configuration file: import { createLocalVue } from '@vue/t ...

Acquiring the $parent.$index variable within a custom directive

<li ng-repeat="value in array1 track by $index"> <div ng-repeat="j in array2"> <div example-directive > <p> {{$index}} ,{{$parent.$index}}</p> </div> </div> </li> Within t ...

The target for ajaxSubmit is being duplicated instead of being replaced

I encountered a problem with the code below: $('#refresh').click(function () { alert($('.report-container').length); $('.report-container').each(function () { var accordian = this; var url = $(this) ...

Import reactjs modules without the need for Browserify, Webpack, or Babel

I am attempting to set up a TypeScript HTML application in Visual Studio. My goal is to incorporate reactjs v0.14.7 without relying on tools like Browserify. But, how can I utilize the react-dom module in this scenario? Let's set aside TypeScript fo ...

Adding the expanded search icon to a text box in Vuetify: A step-by-step guide

Recently, I integrated Vuetifyjs into my right-to-left (RTL) Vue 2 project. Within a card element, I inserted a table and included a search bar following the documentation. Now, I have two specific goals in mind: Relocate the "number of items to show" opt ...

Finding the appropriate method to access a template variable reference in a designated row of an Angular Material table (Angular 7)

Currently, I am working on implementing a more intricate version of a behavior inspired by Angular Material's tutorials. In my simplified example, an Angular Material table is populated with data from a string array. The first column contains input fi ...

HTML embedded content is not appearing on the React webpage

I'm attempting to incorporate GoFundMe donation buttons into a React page, but unfortunately, they aren't displaying on the screen. const Donation = () => { return ( <div> <div className="gfm-embed" d ...

Issue with JQuery dialog not triggering autocomplete

I have integrated the JQuery 1.7.2 and JQuery-UI 1.8.18 libraries with both http://docs.jquery.com/UI/Dialog and http://docs.jquery.com/UI/Autocomplete. On a standard page load, the autocomplete function works perfectly with a text box in a form. It' ...

Discovering dependencies for the Tabulator library can be achieved by following these

Can anyone provide me with a complete list of dependencies for Tabulator 4.2? I have already reviewed the package.json file, but it only contains devDependencies. ...

Caching of audio files in React streaming is enabled

My dilemma lies in the fact that despite creating a new file in the back-end, the <PlaySound /> component continues to play the old sound file rather than the updated one. Although the sound file maintains the same name and path, its content differs. ...

What is the best way to modify an image in a column when I hover over a table row that was dynamically inserted using a button function?

Is there a way to dynamically change an image in a column when hovering over a table row that was added through a button function? Here is the current code that I am using, but it does not seem to work as intended when I hover over the row. This function ...

Execute a PHP function when a post is clicked using JavaScript

I have a script that shows an image depending on database results. When a user clicks the image, it changes to a new one. The green_star signifies that both $user_id and $thedb_id are in the database, while the grey_star indicates they are not. I want to b ...

Having trouble processing a JSON object using Jquery?

Hello, I am currently working on parsing a JSON object using jQuery. So far, I have successfully extracted all the necessary information from the results except for one crucial piece - the performance tags. Each JSON result is enclosed in an event tag and ...