Dynamics CRM - JS ReferenceError "X" is not defined - javascript

I have a short bit of Javascript that sets fields to optional for certain forms.
I've checked syntax multiple times, checked the execute order in the CRM Form, and there are no references to other JS Libraries.
function getFormName() {
var formName;
formName = Xrm.Page.ui.formSelector.getCurrentItem().getLabel();
if (formName == "EPS Plan Form") {
Xrm.Page.getAttribute("abc_plan_type").setRequiredLevel("none");
Xrm.Page.getAttribute("usi_erisa_plan").setRequiredLevel("none");
Xrm.Page.getAttribute("abc_product").setRequiredLevel("none");
}
}
The error I'm getting seems to be in reference to general syntax issues :
ReferenceError: getName is not defined
at eval (eval at RunHandlerInternal
at RunHandlerInternal
at RunHandlers
at OnScriptTagLoaded

Seems like your event trigger on the form might be configured to call a function called getName...
If you check the form Properties > Events, do you see a call to getName in the OnLoad event? Based on your function name above you'd need it to call getFormName.
And for the record, Xrm.Page is deprecated in favor of passing execution context and using executionContext.getFormContext() (except when referencing the parent page from a web resource, in which case Xrm.Page is still supported, last I heard.)

Related

OfficeJS addHandlerAsync callback does not execute angular component method

I am working on an outlook web add-in (in Angular 5) and I am implementing a pinnable task pane and I've been following this documentation from Microsoft : Implement a pinnable task pane in Outlook.
What I want to do is when the selected mail in Outlook was changed, I need to update the content of my task pane UI.
On My Component.TS
I added the following addHandlerSync event listener for change on mail selection:
ngOnInit() {
Office.context.mailbox.addHandlerAsync(Office.EventType.ItemChanged, this.selectMailChanged);
}
selectMailChanged(){
this.getPhoneNumbers() //This function gets phone numbers on the email
}
The error of the above code is
this.getPhoneNumbers is not defined.
I tried enclosing this this.getPhoneNumbers on zone (based on MS Documentation: Trigger the UI update) but it returns zone.run is not defined.
How can I call an angular component method on addHandlerAsync callback?
Good old famous this keyword problems.
You're getting that error message because of the context difference. When you're writing the code, the method selectMailChanged references the method getPhoneNumbers (which I'm hoping you have it implemented) in your component. So coding-wise it looks good.
But when the event kicks in - it doesn't have the context of the component anymore, because it's just calling a callback function - so it doesn't really have all the outside world information except the function that it's calling into. You can read a few good answers about this below:
How to access the correct `this` inside a callback?
https://thenewstack.io/mastering-javascript-callbacks-bind-apply-call/
https://technology.amis.nl/2016/08/23/access-the-original-calling-context-in-a-callback-function-in-typescript/
Move the functionality in getPhoneNumbers to the callback method and you shouldn't have this problem.

Javascript structured error handling

I am developing my first Javascript app and I am trying to go object oriented.
There is a basic closure that returns my primary object and every function I invoke rests in that object. Some pseudo code would look like this:
primary = (function(){
var object = {
doSomething = function(){};
},
return {intance:function(return object)}
});
//invocation
primary.instance().doSomething();
What I am trying to achieve is to attach an error handler function to my object, so that whenever there is an internal error, it is cought, and I don't have to wrap every function call in a try catch block.
I tried object.onerrorbut the error went on to window object. Maybe I am getting the concept wrong. I tried searching on Github for some simpler framework that includes structured error handling, but no luck. I am pretty familiar with this in PHP, but I haven't done this so far in Javascript. Can somebody show me an example how it is done right?
EDIT: I know that structured error handling goes further, I am just trying to get a root handler, so that no errors / exceptions can pass on to the window object
Dealing with the error event without a try catch block will halt the execution of your script (except for any asynchronous functions that have already been called).
You can suppress (non-ajax, non-syntax) errors by capturing them on document.body or a more specific object, and stop them being thrown to the user (or reaching the window object) by using e.preventDefault() or return false, and send them to a global/object handler (to inspect or log) by passing the event object as an argument - but any of those options will stop your script execution beyond the point of error. That's the main benefit of a try catch block, and as far as I know there is no way around that.

Javascript variable function method call

I apologise if this has been asked elsewhere, I looked but without knowing the name for what I am doing is, I couldn't find anything.
Anyways, the code is as follows:
function alertTypeOptions(AlertType, AlertOptions) {
navigator.notification.AlertType(AlertOptions);
}
This code is for a phonegap / cordova application.
The basic idea is that you pass the function a two variables and these are used to execute the appropriate method. Examples of this could be alertTypeOptions('beep', '3') or alertTypeOptions('vibrate', '2000'). This (should) play the default alert tone 3x or vibrate the phone for 2 seconds.
I am currently getting the following error:
02-21 15:36:07.185: E/Web Console(7206): Uncaught TypeError:
Object #<Object> has no method 'AlertType'
at file:///android_asset/www/res/scripts.js:181
Obviously the function is currently just using the alertType variable as written rather than as a variable.
Is there a way to get this to work elegantly? Currently my only thoughts are to use a switch statement with AlertType as the check.
Jack
It looks like you want to access your function using the bracket notation :
navigator.notification[AlertType](AlertOptions);
or rather, if I trust this documentation and if AlertOptions is an array :
navigator.notification[AlertType].apply(navigator, AlertOptions);

TypeError when running jasmine specs that use a jQuery plugin built using the Widget factory

I'm using a jQuery plugin called toggleEdit for inline editing.
Everything works fine when the code is actually used in the page.
However, my test suite fails with the following error:
TypeError: Cannot call method 'remove' of undefined
I tracked it down to be triggered from within the clear method of this particular plugin. Its source file can be found here.
There are two relevant bits in that code:
1- The _init function
self.element.addClass("toggleEdit toggleEdit-edit toggleEdit-edit-" +
self._tag(self.element))
//store reference to preview element
.data("toggleEdit-preview", self.p);
As you can see, when the plugin is first instantiated it uses the data structure on self to store the newly created element.
2- The clear function
self.element.data("toggleEdit-preview").remove();
The clear function then tries to access that structure and retrieve the element. That's when, while inside a jasmine spec, it fails with the aforementioned exception.
Has anyone seen anything similar?
EDIT:
This is my spec, it's the simplest piece of code able to reproduce the error:
it("should update the given attribute on the server", function(){
$('#user-details input, #user-details select').toggleEdit(); //this line triggers the error
});
http://alz.so/static/plugins/toggleedit/jquery.toggleedit.js
I was taking a look at the source for toggleEdit and it seems that the only 2 times the function clear is called is just before self.element.data gets set:
if (typeof self.element.data("toggleEdit-preview") !== "undefined") {
self.clear();
self.disableEvents();
}
And at destroy function:
destroy: function() {
var self = this;
self.clear();
self.disableEvents();
$.Widget.prototype.destroy.apply(self, arguments);
}
Since the first call seems to be protected, I ask you a somewhat dumb question: Is it possible that destroy is being called twice?
Found my problem: old version of the jQuery + jQuery UI duo. Upgrading them resolves the exception.

variable assignments using jQuery failing in Safari?

I'm using jQuery 1.3.2 and it's breaking under Safari 4 for mysterious reasons.
All of my javascript references are made right before the tag, yet with the following code:
var status = $('#status');
status.change( function(){ /* ... */ } );
The following error is displayed in the Web Inspector:
TypeError: Result of expression 'status.change' [undefined] is not a function.
However the error is not encountered if I eliminate the variable assignment attach the change method directly like so:
$('#status').change( function(){ /* ... */ } );
Why? I need to use variables for this and several other findById references because they're used many times in the script and crawling the DOM for each element every time is regarded as bad practice. It shouldn't be failing to find the element, as the javascript is loaded after everything except and .
Try changing the variable to something other than "status."
It's confusing your variable with window.status (the status bar text). When I typed var status = $('#status') into the debugging console, the statusbar changed to [Object object]. Must be a bug in Safari.
If you put the code inside a function, so that status becomes a function-local variable, it should work.
It's standard practice in jQuery to wrap things in a
$.onready(function() {
});
This makes sure the DOM is loaded before you try to manipulate it.

Categories

Resources