Search code examples
javascriptangularjspostmessage

When AngularJS controller meets postMessage events


I have the following code which uses AngularJS and a message listener: JSBin:

<!DOCTYPE html> 
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
  <div ng-app="myApp" ng-controller="myCtrl">
    <input type="text" ng-model="Name"><br>
    <br>
    <textarea id="myText" ng-model="Name"></textarea>
  </div>
  <br>
  <span id="fromQuery"></span>

  <script>
    var prefix = "pre-";
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
      function render() {
        document.getElementById("fromQuery").innerHTML = prefix + $scope.Name  
      }

      $scope.Name = "John";

      $scope.$watch('Name', function() {
        render();
      })
    });

    function receiveMessage(event) {
      prefix = event.data;
    }

    window.addEventListener("message", receiveMessage, false);
  </script>
</body>
</html>

AngularJS defines a controller, which permits of synchronising everything: any change to input or textarea will impact input, textarea and the span. I also have a global variable prefix which always adds a prefix to the content of input or textarea and display it in span.

What complicates the case is the listener. Another web page will send this web page new prefixes (sorry I could not show the test here). At the moment, once the page receives a new prefix, it cannot call render because of the function scope, as a consequence, span is not refreshed with the new prefix. What I want to realise is that, once the page receives a new prefix, it refreshes systematically the span with the new prefix.

Does anyone know how to realise this?


Solution

  • angular script : using $window

        var app = angular.module('myApp', []);
        app.controller('myCtrl', function ($scope, $window) {
            $scope.prefix = "abc";//if prefix needs to change dynamically why not add it to scope ?
            function render() {
                document.getElementById("fromQuery").innerHTML = $scope.prefix + $scope.Name
            }
    
            $scope.Name = "John";
    
            function receiveMessage(event) {
                console.log(event.detail); //just checking
                $scope.$apply(function(){          
                    $scope.prefix = event.detail;
                 })
                //$scope.prefix = event.detail;
            }
    
            $window.addEventListener("message", receiveMessage, false);
    
            $scope.$watch('Name', function () {
                render();
            })
           $scope.$watch('prefix', function() {
            console.log('prefix changed');
           render();
           })
        });
    

    html + script for testing

    <button type='button' onclick="doo()">TEST</button>
    

    -

    function doo() {
        var event = new CustomEvent('message', {
                'detail' : 'MyNewPrefix'
            });
        window.dispatchEvent(event);
    }
    

    If this is not what you wanted please let us know.