Skip to main content

Define multiple Angular apps in MVC layout and content page

Here is the situation I encountered: I have a MVC application, in layout.cshtml file, I have a header logo and footer logo and I want the logos to be dynamic based on the client information passed in.

Here is my layout page:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>For your security - Mercer.MFA.SharedUI</title> <base href="~/" /> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" /> <link rel="stylesheet" href="~/css/magic-check.css" /> <link rel="stylesheet" href="~/css/site.css" />
</head> <body> <div class="container"> <header ng-app="headerApp" ng-controller="headerCtrl"> <div class="row"> <div class="col-md-6 header_left"><img ng-src="{{headerLogo}}" alt="logo"></div> <div class="col-md-6 header_right"><!-- Nothing goes in here --></div> </div> </header> <main> <div class="page"> <div #alertPlaceholder id="alert_placeholder"></div> @RenderBody() </div> </main> <footer ng-app="footerApp" ng-controller="footerCtrl"> <div class="row"> <div class="col-md-6 footer_left"><p>© 2017 ALL RIGHTS RESERVED.</p></div> <div class="col-md-6 footer_right"><img ng-src="{{footerLogo}}" alt="logo"></div> </div> </footer> </div> <script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script> <script src="~/lib/angular.1.3.6.min.js"></script> <script> var headerApp = angular.module('headerApp', []); headerApp.controller('headerCtrl', ['$scope', function ($scope) { var customImageUrl = baseUrl + "images/" + sessionStorage.client + "/logo.png"; $.ajax({
url: customImageUrl, success: function (data) { $scope.headerLogo = customImageUrl; }, error: function (data) { $scope.headerLogo = "images/logo.png"; } });
}]); var footerApp = angular.module('footerApp', []); footerApp.controller('footerCtrl', ['$scope', function ($scope) { var customImageUrl = baseUrl + "images/" + sessionStorage.client + "/footer.png"; $.ajax({
url: customImageUrl, success: function (data) { $scope.footerLogo = customImageUrl; }, error: function (data) { $scope.footerLogo = "images/footer.png"; }
}); }]); </script> @RenderSection("scripts", required: false) </body> </html>

In content view, I have another angular controller defined.
<script>
    var myApp= angular.module('myApp', [])
    homeApp.controller('homeCtrl', ['$scope', '$http', function ($scope, $http) {  ... }]);
</script>
<div id="homePage" ng-app="myApp" ng-controller="homeCtrl" ng-init="init()">

However, I always got 'headerCtrl' is not a function error. After google, I found out if in one page, there are more than one Angular apps, you have two options to make it work:

1. Manually bootstrap each app in Angular:
In content view, add manual bootstrap code:

<script>
    var myApp= angular.module('myApp', [])
    homeApp.controller('homeCtrl', ['$scope', '$http', function ($scope, $http) {  ... }]);
var elHeader= document.getElementByTagName('header');
var elFooter= document.getElementByTagName('footer');
var homeDiv = document.getElementById('homePage');
angular.element(document).ready(function() { angular.bootstrap(elHeader, ['headerApp']); angular.bootstrap(elFooter, ['footerApp']); angular.bootstrap(homeDiv, ['myApp']);
})
</script>

Since we are bootstrapping them manually, make sure to remove all the ng-app attribute from the HTML page.

2. Inject header and footer apps to main app:
In content view page, using following code to declare the myApp Angular app:
<script>
    var myApp= angular.module('myApp', ['headerApp','footerApp'])
    myApp.controller('homeCtrl', ['$scope', '$http', function ($scope, $http) {  ... }]);
</script>
In layout page and content page, remove all the ng-app attributes. Add ng-app="myApp" to the body element:
<body ng-app="myApp">

Enjoy coding!

Comments

Popular posts from this blog

Manage IIS 7 remotely using PowerShell and AppCmd

We can use  Windows PowerShell remoting features  to manage IIS 7 websites remotely.  Currently, remoting is supported on Windows Vista with Service Pack 1 or later, Windows 7, Windows Server 2008, and Windows Server 2008 Release 2.  Start Windows PowerShell as an administrator by right-clicking the Windows PowerShell shortcut and selecting Run As Administrator .  Enable PowerShell Remoting with Enable-PSRemoting -Force Starting a Remote Session using:  Enter-PSSession -ComputerName <COMPUTER> -Credential <USER> Now the PowerShell connected to the remote server. Any commands issued with work against the remote server. We can use the Appcmd.exe command line tool to manage remote server just as what we do locally. For example, to add an application pool: c:\windows\system32\inetsrv\appcmd add apppool /name:"Contoso" /managedPipelineMode:Integrated /managedRuntimeVersion:"v4.0" /enable32BitAppOnWin64:true To change application pool for a

X509Certificate2: The system cannot find the file specified.

When I use the new X509Certificate2(fileName, password, X509KeyStorageFlags.DefaultKeySet) to create certificate from certificate file containing private key in my web application, I got following error message: System . Security . Cryptography . CryptographicException : The system cannot find the file specified . at System . Security . Cryptography . CryptographicException . ThrowCryptogaphicException ( Int32 hr ) at System . Security . Cryptography . X509Certificates . X509Utils . _LoadCertFromBlob ( Byte [] rawData , IntPtr password , UInt32 dwFlags , Boolean persistKeySet , SafeCertContextHandle & pCertCtx ) at System . Security . Cryptography . X509Certificates . X509Certificate . LoadCertificateFromBlob ( Byte [] rawData , Object password , X509KeyStorageFlags keyStorageFlags ) at System . Security . Cryptography . X509Certificates . X509Certificate2 .. ctor ( Byte [] rawData , String password , X509KeyStorageFlags keyStorageFlags ) In orde

Entity framework code first error: OriginalValues cannot be used for entities in the Added state

When I was using Entity framework code first, I encountered an error when I tried to create an entity into database. The entity is: [ Table (" EmployeeProfile ")]     public partial class EmployeeProfile     {         [ Key ]         [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]         public int EmployeeProfileID { get; set; }         [ ForeignKey ("Employee")]         public int EmployeeID { get; set; }         public virtual Employee Employee { get; set; }         [ ForeignKey (" Profile ")]         public int ProfileID { get; set; }         public virtual Profile Profile { get; set; }         [ Required ]         [ StringLength (255)]         public string ProfileValue { get; set; }     } When creating the entity, some entities have the ProfileValue="", this causes the EntityValidationException with the detailed message " OriginalValues cannot be used for entities in the Added state ". I want to allow the Prof