Finding angular scope from javascript
No edit summary
No edit summary
Line 32: Line 32:
  });
  });
You can then use angularjs functions lite $watch to find out when data is available or changed like this (this example was taken from a bank integration for easyarr - Swedbank ):
You can then use angularjs functions lite $watch to find out when data is available or changed like this (this example was taken from a bank integration for easyarr - Swedbank ):
sss
<pre>
    var initiated=false;
function startTheProcess() {
console.log('startTheProcess');
//debugger;
var thescope=angular.element('#viewmodelWrapper').controller().$scope;
//thescope.ViewModelRoot.ConsumerId=""; // so that we restart if we get the same value
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');
}
</pre>

Revision as of 08:30, 10 August 2021

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 go like 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 signaling of 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). In order 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 it will call a function startTheProcess after the data has been bound in Angular (data need not have downloaded - but it is bound bu angularjs)

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

You can then use angularjs functions lite $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;
		//thescope.ViewModelRoot.ConsumerId=""; // so that we restart if we get the same value
		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 97 days ago on 02/10/2024. What links here