Challenge 1: The FormController of the AngularJS framework is based on the form HTML element. That means, if we would like to use the features of the FormController, like dirty / pristine, validation, etc., we should include a form element in our HTML application. However, our SharePoint page is an ASP.NET page, that already contains a form element, and it does not like to include multiple ones.
Solution 1: Although there are tricks to bypass this limitation (like this or this one), I chose another way to go. I’ve included a Page Viewer Web Part that displays a “pure” HTML page that is stored in a document library in SharePoint, as well as any other non-standard artifacts of the application (.js and .css files, etc.). This HTML page – displayed in an IFRAME by the Page Viewer Web Part – contains the form element, that does not interfere with the form element on the ASP.NET page.
TypeError: Unable to get property ‘addNotification’ of undefined or null reference
Challenge 2: There is no notification / status message displayed, even if you add the reference to the sp.js. The reason of the problem is, that the HTML elements required by these methods are defined in the master page of the standard SharePoint sites. Obviously, these elements are not found in our custom page in the IFRAME, so the messages are not displayed.
Solution 2: I’ve found two similar blog posts (this one and this one) describing a similar issue with IFRAME and notification messages in the case of Client App Parts. The first of this two posts states that the problem is the IFRAME itself, that prohibits the communication between the parent page and the IFRAME. Of course, that is wrong. The real reason is the different domain names in the URL of the app part (IFRAME) and the host page, as correctly stated in the second post. If we have the same domain name (and we do have in this case), we do not need the rather complex approach described by the posts(that is still valid for the Client App Parts). Displaying a notification / status message from the script included in the HTML page in the IFRAME in our case is so simple as to prepend the text ‘parent.’ before the method invocation, for example:
var notifyId = parent.SP.UI.Notify.addNotification("Saving…", true);