Anonymous callback function to JsObject doesn't update Dart Controller until after a user action

Issue

Given the dart code

class LandingController {
  bool hideDiv = false;

  void doit() {
      new JsObject(context['loginControls']).callMethod('fadeLogin', [() {
         print(hideDiv);
         hideDiv = true;
         print(hideDiv);
         print("WTF");
      }]);
  }
}

which calls the JS:

var loginControls = function() {
  this.fadeLogin = function(func) {
    $('#landingHeader').animate({ opacity: 0 }, 500, func);
  }
};

which should affect the view:

<button ng-click="doit();">Click</button>
<div id="landingHeader">Hide me after button click</div>
<div ng-if="ctrl.hideDiv == false"><img src="assets/img/ajax-loader-small.gif">Waiting for div to disappear...</div>

After a button click and a 500 millisecond delay I see in my console a “WTF” print correctly. The div, however, is still visible. Once a user action occurs, in my case a mouse click, the div magically disappears. It seems as though the controller’s value is changed, but the browser doesn’t receive the change to hide the div, as I’ve printed the controller’s value in the anonymous callback.

There is a work around, but it involves setting Dart timer’s to the same fade times that you use in the javascript after the JsObject call and setting your controller’s values in those Timer callbacks – gross but it works.

Solution

I think you need to call scope.apply(). I think Angular just can’t recognize the value change in hideDiv when doit() is called from another zone (like JS).

You usually don’t need to call scope.apply() in Angular.dart but I think this is one of the exceptions.

Is the animate function the only reason you use jQuery? It might be easier to do this with Angular.darts animation features.

Answered By – Günter Zöchbauer

Answer Checked By – Candace Johnson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.