Finding angular scope from javascript

When working with EXT_Components and integrating towards other services, you may end up in situations where you get callbacks in client-side javascript - and you will want to catch data from such a callback.

To get hold of your objects from such a callback (that are outside of the normal Angular realm where you have some scope information at hand), you can do this:

var vmroot=angular.element('#viewmodelWrapper').controller().$scope.ViewModelRoot;

You now have the current local representation of your ViewModel in the vmroot variable and you can set properties like this:

vmroot.MyViewModelColumn=somevalueFromACallBack;

MDrivenTurnkey sees the property you change and handles the signaling of the server and binding of UI.

With some defensive error checking:

      function GetVMRoot(){
	var ctrl=angular.element('#viewmodelWrapper').controller();
        if (ctrl !== undefined){
           return ctrl.$scope.ViewModelRoot;
        }					
        return undefined;      
      }

Alternative Approach

Depending on what your needs are, it may be better to inject the result into a UI control and let AngularJS handle the databinding to move that data into the underlying ViewModel-object-column-property (then Turnkey will discover the change and stream it to the server). To let AngularJS know that the code you use to set the value should be handled as a user interaction of the input, you must dispatch the change event. Something like this:

function setResult(label, result) {
  let someelem=document.getElementById('BiljettCheck.Id');   // find the input elem bound to ViewModel "BiljettCheck" and Column "Id"
  someelem.value=result;                                     // assign a new value to the input
  var event = new Event('change');    
  someelem.dispatchEvent(event);                             // signal to listeners (angularjs) that the value has changed
}

Acting after Angular Page Has Fully Loaded

The script below can be added to your page and will call a function StartTheProcess after the data has been bound in Angular (data need not have been downloaded - but it is bound by AngularJS)

angular.element(function () {
  console.log('page loading completed');
  startTheProcess();
});

You can then use AngularJS functions like $watch to find out when data is available or changed like this (this example was taken from a bank integration for EasyArr - Swedbank):

        var initiated=false;	
	function startTheProcess() {
				
		console.log('startTheProcess');
		//debugger;
		var thescope=angular.element('#viewmodelWrapper').controller().$scope;
		if (!initiated){
			initiated=true;
			thescope.$watch('ViewModelRoot.DataIsLoaded', function (newv, oldval, thescope) {
				console.log('startTheProcess WATCH DataIsLoaded '+newv);
				if (newv=="DataIsLoaded"){
					thescope.ViewClient.CallServerAction('SwedbankPay','SCRIPTSCALLCheckIn',null); // handles the case when we called CheckIn too early 
				  }
				});
			thescope.$watch('ViewModelRoot.FetchedScriptUrlForCheckin', function (newv, oldval, thescope) {
				console.log('startTheProcess WATCH FetchedScriptUrlForCheckin '+newv);
				if (newv && newv!=""){
					  DoCheckInScript(newv,thescope);
				  }
				});
			thescope.$watch('ViewModelRoot.FetchedScriptUrlForPaymentUI', function (newv, oldval, thescope) {
				console.log('startTheProcess WATCH FetchedScriptUrlForPaymentUI '+newv);
				if (newv && newv!=""){
					  DoPaymentUIScript(newv,thescope);
				  }
				});
			thescope.$watch('ViewModelRoot.ConsumerId', function (newv, oldval, thescope) {
				console.log('startTheProcess WATCH ConsumerId '+newv);
				if (newv && newv!=""){
					  DoPaymentOrderForThisConsumerProfile(newv,thescope);
				  }
				});
				
			
		}
		else{
				console.log('startTheProcess - init skipped');
		}

		thescope.ViewClient.CallServerAction('SwedbankPay','SCRIPTSCALLCheckIn',null)
		console.log('startTheProcess CheckIn');
	
	}
This page was edited 68 days ago on 02/10/2024. What links here