I struggled for a long time to get this to work. What it comes down to is that you have to do the bootstrapping process manually. You can not use the ng-app directive too do the bootstrapping. Refer to the Manual Initialization section of the official documentation for further information. I have copied and pasted my code below for how I did it. I am also injecting a constants object called CONFIG into my angular app. This contains a bunch of useful information that can be used within the instance of the angular app. I am using some advanced javascript to define constants... it's ugly, but it's just how you define constants in ES5. I should note that there are a couple of properties I define in the javascript CONFIG object that are not members of PortalModuleBase, such as <%= this.CurrentLocaleResxJson %>. These are just custom properties existing in my code behind file View.ascx.cs. I use these custom properties to inject some useful information into the instance of the angular app. They can be safely ignored, and you should just use this as a guideline for how to inject information from DNN into your angular app. The most important one that does exist as a member of PortalModuleBase is <%= this.ModuleId %>, everything revolves around this unique ID. It's the only one your need to worry about to get started.
This will allow you to have multiple instances of your DNN module to exist on the same page, because <div id="app-<%=this.ModuleId%>"> will be a self contained angular app. I should also note that you should load the angular.js library in the of your DNN page, otherwise you may run into issues. Refer to the Client Resource Management wiki article for how to do this. Stare at the code below for a while and it should become more clear of how you should approach this. Best of luck, angular is amazing and well worth investing in.
View.ascx
<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="View.ascx.cs" Inherits="Zen.Modules.ZenAngular.View" %>
<div
id="app-<%=this.ModuleId%>">
<ui-view>
Loading...
</ui-view>
</div>
<script>
(function () {
'use strict';
var CONFIG = (function () {
function CONFIG() {}
Object.defineProperty(CONFIG, "MODULE_ID", {
get: function () { return <%= this.ModuleId %>; }
});
Object.defineProperty(CONFIG, "MODULE_NAME", {
get: function () { return '<%= this.ModuleName %>'; }
});
Object.defineProperty(CONFIG, "MODULE_PATH", {
get: function () { return '<%= this.DnnModulePath %>'; }
});
Object.defineProperty(CONFIG, "APP_PATH", {
get: function () { return '<%= this.DnnModulePath %>' + 'Resources/app/'; }
});
Object.defineProperty(CONFIG, "CAN_EDIT", {
get: function () { return <%= this.CanEdit %>; }
});
Object.defineProperty(CONFIG, "CULTURE_CODE", {
get: function () { return '<%= this.CurrentCultureCode %>'; }
});
Object.defineProperty(CONFIG, "LOCALE_RESOURCES", {
get: function () { return <%= this.CurrentLocaleResxJson %>; }
});
return CONFIG;
})();
angular.element(document).ready(function () {
angular.module('zen.angularApp').constant("CONFIG", CONFIG);
var
appContainer = document.getElementById('app-<%=this.ModuleId%>');
angular.bootstrap(appContainer, ['zen.angularApp']);
});
})();