The callback within an Angular directive is triggered before the model is updated

There is an issue with a directive that has a model and callback mapped to the parent scope. The problem arises when the parent model is updated after the callback has occurred, even though in the code it is assigned before.

DEMO: PLUNKER (Click twice or more and you will see that the model is updating after the click callback)

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

app.controller('MainCtrl', function($scope) {
  $scope.test = true;
  $scope.test2 = true;
  $scope.triggerCallback = function()
  {
      $scope.test2 = $scope.test;//it always see previous value here
  };
}).directive('testdirective', [function () {
    return {
        restrict: 'A',
        template: '<span ng-click="clicked()">from directive: {{checked}}</span>',
        replace: true,
        scope: {
            bindModel: '=ngModel',
            clickCallback: '&onClick'
        },
        link: function (scope, element) {
            scope.checked = scope.bindModel;

            scope.clicked = function () {
                scope.checked = !scope.checked; 
                scope.bindModel = scope.checked;//MODEL UPDATE


              //callback is called AFTER model updating, but model is updated after that
                if (scope.clickCallback != undefined)
                    scope.clickCallback();
            };
        }
    }
}]);

html:

<body ng-controller="MainCtrl">
    <a href="">
      <div testdirective ng-model="test" on-click="triggerCallback()"></div>
    </a>
    <br/>
    <span>{{test2}}</span>
  </body>

Although a workaround can be implemented by passing the new value in the callback function, in certain situations it may not be sufficient. Therefore, a more straightforward resolution is desired.

Answer №1

A common error in two-way-data-binding is overlooking a critical step.

While $scope.$apply can be a solution, you may encounter the $digest already running exception. In such cases, utilizing $timeout becomes necessary as it will only execute after the current digest-cycle is complete.

$timeout(function(){
  if (scope.clickCallback != undefined) 
    scope.clickCallback(); 
  };
});

For further insight into the angular lifecycle, refer to:

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

Issue encountered while attempting to load external JSON file from server in AngularJS

Currently, I am attempting to load a JSON file from the server. Below is my services.js file: angular.module('starter.services', []) /** * A simple example service that returns some data. */ .factory('Friends', function($http) { ...

What are the various ways to apply unique padding styles to ng-repeat items?

Take a look at this image. I need to position my 6 boxes on the 6 vertical lines above the image. I am struggling with applying different padding styles to my ng-repeat directive. Although I tried using [ng-class], it doesn't seem to work as expected. ...

Avoid triggering the onClick event on multiple submit buttons when the form data is deemed invalid by vee-validate

How can I ensure that the onClick event on a button is only called if certain input fields are valid, using vee-validate ValidationObserver? The validation should apply to individual buttons within a form, rather than the entire form itself, as there are m ...

Can the Route be modified in Next.js?

I have developed search functionality that navigates to "/search/xxxx", but it is located in the header. Every time I perform a search, the route gets repeated and becomes "/search/search/xxx". Could you suggest any way other than usin ...

Encountering a syntax error close to an unexpected token '../lib/cli.js' while attempting to launch an application through pm2 start

I'm encountering an issue while executing pm2 start with an ecosystem.config.js /root/.nvm/versions/node/v18.16.0/bin/npm: line 2: require('../lib/cli.js')(process)' /root/.nvm/versions/node/v18.16.0/bin/npm: line 2: syntax error near u ...

Can the Twitter Bootstrap typeahead feature be used with an external data source?

Can the typeahead feature in version 2.0.3 of twitter-bootstrap work with a remote data source? You can check out the link for more information on the typeahead functionality: ...

Sending modal data to a different page with AngularJS

Looking to transfer information from a modal to another page? The promise function in my modal is set up like this: modalInstance.result.then(function (product) { $scope.selectedProduct = product; $location.path('cart'); ...

Sharing a Detailed Mongoose Schema

Hey there! So, I've been working on this Mongoose Schema and there seems to be something off about it. The main area of concern is the "region" part. const mongoose = require('mongoose'); const destination = new mongoose.Schema({ ...

When implementing a helper function in ejs with .then, the result returned is an [ object promise ]

I am facing an issue in my ejs file where I am invoking a helper function from another file that should return a result from MySQL. However, the problem lies in the fact that the returned value is showing as [ object promise ] even though I am using .then( ...

angularJS transformRequest for a specified API call

Looking for a way to pass multipart/formdata through a $resource in Angular so I can post an image. I discovered a helpful solution on this Stack Overflow thread. However, the solution applies to all requests within my modules, and I only want it to apply ...

Deactivate multiple input fields by utilizing various radio buttons

I need help with enabling and disabling input fields based on radio button selection. When the first radio button is selected, I want to disable three input fields, when the second is selected, only two specific input fields should be enabled (SHIFT START ...

Rating of displaying an undefined value (NaN)

I'm having issues with creating a currency conversion calculator, as the result is showing as NaN. Can anyone offer assistance? I've tried multiple solutions but have been unable to resolve it. Check out the following JavaScript code snippet: c ...

Create a React component using the value stored within an object

I am interested in creating an object: import React from "react"; import { Registration } from "../../"; const RouteObj = { Registration: { route: "/registration", comp: <Registration /> } }; export default RouteObj; Next, in a separat ...

The typical initial default argument to be passed to the function using fn.apply

Recently, I discovered the power of using fn.apply() in JavaScript to store function calls with all their arguments intact for future use. In my specific situation, I don't require the first argument, which is the context (this), and I want to find a ...

Why is the time input field in AngularJS programmed to expect a date instead?

When booking, I stored the time using $filter('date')($scope.booktime, 'mediumTime'). After booking, I have an editbooking function where I pass the time and encounter an error in the console: Error: [ngModel:datefmt] Expected 11:59:00 ...

What is the process for setting environment variables in a Svelte project?

I'm brand new to working with Svelte and I want to incorporate environment variables like base_url into different components. I've read that I can set up a store to hold these values, for example: const DataStore = writable([ { base_url: & ...

The ESLint rule "eqeqeq" configuration is deemed incorrect

After successfully running eslint with the provided .eslintrc file, I encountered an issue when making a simple change to use 'standard' instead of 'airbnb-base' as the extend: module.exports = { root: true, parser: 'babel-esl ...

Identify the Presence of Hover Functionality

For a while now, the trend has been leaning towards feature detection. I am interested in determining whether a visitor's browser supports the :hover pseudo class. With many mobile devices not supporting hovering, I want to adjust my event listeners a ...

Mistakes while utilizing the yarn package manager

Lately, I've been relying on using sudo with npm to install packages, but I've come to realize that this is not a good practice. In light of this, I decided to switch to yarn for managing my packages. However, I'm encountering some errors af ...

Role-based dynamic layout

I am currently working on a website that requires user login functionality. To achieve this, I am utilizing materialise-css and Angularjs for the front-end development, while the back-end is powered by Java-Hibernate (as Spring is not an option in my case) ...