Calling widget's client controller from Body HTML script tag

Nisar2
Mega Guru

I've the following in the Body HTML template of widget.

 

Nisar2_0-1698236053729.png


The alert is working. But I've not been able to figure out how to pass that info to the client controller or server side. Any suggestions?

1 ACCEPTED SOLUTION

I have never tried pulling in React in Service Portal, but the following might work.

In the client controller define some variables on $scope or c.

api.controller = function($scope){
    var c = this;
    $scope.geoLoc = {
        "lat": "",
        "long": ""
    };
    
    //to test if this works watch the variables for changes and log out values
    $scope.$watch( 'geoLoc ', function (newValue, oldValue ) {
        if(newValue.lat || newValue.long)
            console.log(newValue)
    }, true)
...
}

 

Since your React script is outside AngularJS scope you'll need to grab it within the script tags in the HTML template. You'll also want to wrap within a setTimeout to ensure the elements are present before the script runs.

 

  <script>
    
    setTimeout(function(){
        var scope = angular.element('#Geo_Map_root').scope();
        let locTimer;
        const loadLocationMap = () => {
          const { LocationMap } = window.geoJsLib;
          const root = ReactDOM.createRoot(document.getElementById('Geo_Map_root'));
          const onSubmit=(location) => {
            scope.geoLoc.lat = location.latitude.toString();
            scope.geoLoc.long = location.longitude.toString();
          }
          root.render(React.createElement(LocationMap, { onSubmit }, null));
        }
    },500);
    
  </script>

 

I know that doing this works without using React, so theoretically it should work with it.

react_test.gif

View solution in original post

8 REPLIES 8

Watch() triggers when the value is actually changed on the variables it's watching. I have never used React mix with AngularJS and in the Service Portal; so I don't know if that is the issue. However, the watch() isn't needed unless you really are needing it to do something once the value changes. I put that in the script just to have it console log out.


@ChrisBurks wrote:

However, the watch() isn't needed unless you really are needing it to do something once the value changes


Unfortunately, I do need something to happen once the lat/long is selected. I make a call to the server script to update those values in the backend. So I'm assuming $watch() is the only way to do it in this case?

No, $watch() is not the only way. When the script reaches into the scope, if the call to the server script is created on $scope or c, then it is accessible just like the other variables. In this case don't use the $watch(), just pass the data straight to the script that calls to the server.

 

For example I'll replace the $watch() with a script that calls and passes data to the server.

api.controller = function($scope){
    var c = this;
    $scope.geoLoc = {
        "lat": "",
        "long": ""
    };
    
    //pass the longitude and latitude to server
    c.doAnUpdate = function (geoLoc) {
        c.server.get({
            "action":"UPDATE",
            "geoLoc": geoLoc
        })
    }
   //a .then() can be used after teh c.server.get() if you need to bring something back to the client after the server has done. it's job
...
}

 

Now in the HTML <script> use that function

  <script>
    
    setTimeout(function(){
        var scope = angular.element('#Geo_Map_root').scope();
        let locTimer;
        const loadLocationMap = () => {
          const { LocationMap } = window.geoJsLib;
          const root = ReactDOM.createRoot(document.getElementById('Geo_Map_root'));
          const onSubmit=(location) => {
            scope.geoLoc.lat = location.latitude.toString();
            scope.geoLoc.long = location.longitude.toString();
            //New line added below
            scope.c.doAnUpdate(scope.geoLoc);
          }
          root.render(React.createElement(LocationMap, { onSubmit }, null));
        }
    },500);
    
  </script>

 

Server Script:

(function() {
  
	if(input && input.action == "UPDATE"){
		//do what is needed with your values input.geoLoc
	}
})();

 

 

That's great. Thanks. I just wan't sure if I could pass that from the <script> tag. Looks like we can.