Simple adding of Angular to MVC not working? - angularjs

I'm going to make a simple MVC project that uses Angular as well. I think I have everything setup correctly but obviously I'm missing something that is probably simple.
When I run the site and look at the developer tools it looks as though jQuery is loaded before Angular. I don't know why that is or how to force it to load first.
I'm using VS 2015 and created a simple MVC with Web API app. I added the Angular.js v1.5 to my scripts folder, added the ng-app to the body, and added the angular.js to the bundle config file. I did rename the bundle but I don't think that's the issue.
Here is my BundleConfig. I added the angular file to the jquery bundle and renamed it to "tools". I made sure angular came before jquery.
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/tools").Include(
"~/Scripts/angular.min.js",
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
Here is my _Layout page. I changed the name of the bundle in the footer to "tools" to match my bundle. I also added ng-app to my body tag.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - CPP Customer Call</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body data-ng-app="cppApp">
<div class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("CPP Customer Call", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
#Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© 2016 - #DateTime.Now.Year</p>
</footer>
</div>
#Scripts.Render("~/bundles/tools")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
For now I'm just trying to write out a simple expression.
<h2>Angular {{ 1 + 1 }}</h2>
Viewing the page only shows "Angular {{ 1 + 1 }}" and not "Angular 2".

So the issue was that I applied an app name to the ng-app but didn't create a module for it first. This is how I fixed it. Hopefully it helps out someone else.
Create an app.js file. I put it in my Scripts/App/app.js structure.
(function () {
var app = angular.module('cppApp', []); //('moduleName', [array of injected modules])
}());
and updated my BundleConfig.cs to this
bundles.Add(new ScriptBundle("~/bundles/tools").Include(
"~/Scripts/angular.min.js",
"~/Scripts/App/app.js",
"~/Scripts/jquery-{version}.js"));

Related

How to use the same AngularJS controller across multiple MVC script files?

I have created an MVC project and added AngularJS-Material and all required files. I put the AngularJS App on the _Layout.cshtml page as I want to be able to display a toolbar throughout the project.
For each view I was planning on using a different controller but when I reference the controller in a new script file I get an error that says the controller is undefined.
The code below works fine and the only problems I get are when I try to add another view in the #RenderBody() section of the code. On each individual chstml file I am defining a new controller but keeping the same app.
Here is my layout file:
<!DOCTYPE html>
<html ng-app="bPST" ng-controller="layoutCtrl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
<link href="~/Content/angular-material.min.css" rel="stylesheet" />
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-animate.js"></script>
<script src="~/Scripts/angular-aria.js"></script>
<script src="~/Scripts/angular-messages.js"></script>
<script src="~/Scripts/angular-material/angular-material.js"></script>
<script src="~/Ang_Scripts/bpst.js"></script>
</head>
<body>
<div layout="column" layout-fill>
<md-toolbar>
<div class="md-toolbar-tools">
<span>Title </span>
<!-- fill up the space between left and right area -->
<span flex></span>
<md-button ng-click="sideBarFunctions()">Menu</md-button>
</div>
</md-toolbar>
<md-sidenav ng-cloak class="md-sidenav-left md-whitefram-z2" md-component-id="left" md-is-open="sideBarOpen">
<div layout="column" layout-align="space-around stretch">
<md-toolbar>
<h2 style="text-align: center;">Menu</h2>
</md-toolbar>
<md-content layout-padding layout="column" layout-align="start">
</md-content>
</div>
</md-sidenav>
<md-content>
<div class="container body-content">
#RenderBody()
</div>
</md-content>
</div>
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
#Scripts.Render("~/bundles/jquery")
#*#Scripts.Render("~/bundles/bootstrap")*#
#RenderSection("scripts", required: false)
login.js:
var bApp = angular.module('bPST', ['ngMaterial']);
bApp.controller('loginCTRL',function($scope) {
$scope.message = "Login";
});
So the problem was more with the way that I was creating the application in the js file.
I was doing this.
var bPSTApp = angular.module('bPST', ['ngMaterial']);
Then creating the controller like this.
bPSTApp.controller('layoutCtrl', function ($scope) {
//Add coding here
};
when I changed it up to this, it started working.
angular.module('bPST').controller('layoutCtrl', function ($scope) {
//Add coding here
});
Now all I need to do is reference the App in each controller file instead of trying to reference the variable that I was setting in the main JS file.
Also, since I am using the login.js on the login cshtml file, it was only being referenced in that view.
I do get that AngularJS and AngularJS Material is good for Single Page Applications, but there are functions that I want to use that make my application look good and function the way I want.
Got to love newbie mistakes.

AngularJs routing issue 404

I am completely new to the AngularJS, trying to learn MVC with AngularJS, sort of mini SPA. For some reason the AngularJS routing is not working for me. I have tried so many combinations, non of them worked. Any clues what I might have wrong? The error I receive is 'The resource cannot be found' 404 when clicked on the button with a link that MVC does not have view method implemented for. It seems like MVC routing is being processed before angularJs client side routing is:
Layout:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<link href="~/Content/bootstrap-superhero.css" rel="stylesheet" />
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-resource.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Scripts/registration-module.js"></script>
#RenderSection("head", false)
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name xxx", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
</div>
</div>
<div class="container body-content" ng-app="registrationModule">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p></footer>
</div>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Registration", action = "Index", id = UrlParameter.Optional }
);
//routes.MapRoute(
// name: "Application",
// url: "{*url}",
// defaults: new { controller = "Registration", action = "Index" });
}
}
Angular registration:
var registrationModule = angular.module("registrationModule", ['ngRoute','ngResource'])
.config(function ($routeProvider, $locationProvider) {
//$routeProvider.when('/Registration/Courses', { templateUrl: '/Templates/courses.html', controller: 'CoursesController' });
$routeProvider.when('/Registration/Courses', { templateUrl: '/Templates/test.html' });
$routeProvider.when('/Registration/Instructors', { templateUrl: '/Templates/instructors.html', controller: 'InstructorsController' });
$routeProvider.otherwise({ redirectTo: '/' });
$locationProvider.html5Mode(true);
});
View
#model Ang2.Models.Registration.Registration
#{
ViewBag.Title = "Index";
}
<div class="container">
<div class="row">
<div class="navbar navbar-default">
<div class="navbar-header">
<ul class="nav navbar-brand">
<li><span class="navbar-brand"></span></li>
</ul>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>Browse Catalog</li>
<li>Browse Instructors</li>
</ul>
</div>
</div>
</div>
<div ng-view></div>
</div>
Physical files exist:
It seems you are using HTML5 routing mode html5Mode(true), but have not specified the base url, so that angular knows where to start the routing. You could try either disable the HTML5 mode (set it to false), or specify the base using <base> tag.
Note that server-side (C# code) is completely unrelated and not used for client-side routing. Also note that you should not expect your controllers to be called, because angular routing is a client-side only, it does not call the server by itself. Means, "view" will NOT be processed by c#, you will just get plain html.
All in all, it looks you don't need angular routing at all, since you seem to be doing routing server side.

templateUrl for AngularJS (routing)/MVC application never loads templates

We are attempting to create a MVC/AngularJS mini-SPA site using various links found on tutorial sites and others like: AngularJS routing in MVC application with templates. However, clicking on the links appear to load the whole page every time, and the templates are never loaded. I am sure I'm missing something simple, but can't figure it out.
My _Layout.cshtml looks like:
<!DOCTYPE html>
<html ng-app="registrationModule">
<head>
<meta charset=" utf-8" />
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/angular.min.js"></script>
<script src="~/Scripts/angular-resource.min.js"></script>
<script src="~/Scripts/angular-route.min.js"></script>
<script src="~/GrextScripts/registration-module.js"></script>
<script src="~/GrextScripts/user-repository.js"></script>
<script src="~/GrextScripts/user-controller.js"></script>
#RenderSection("SectionInHeader", required: false)
</head>
<body>
<header>
<div class=" content-wrapper">
<div class="float-left">
<p class="site-title">
GREXT
</p>
</div>
<div class="float-right">
<nav>
<ul id="menu">
<li>Home</li>
<li>Users</li>
</ul>
</nav>
</div>
</div>
</header>
#RenderBody()
#RenderSection("scripts", required: false)
</body>
</html>
The ControlPanel/Index.cshtml (the {{5+5}} renders properly as a "10" on the page, this was just to see if the AngularJS was working
#{
}
<div ng-view>
{{5+5}}
</div>
registration-module.js
var registrationModule = angular.module("registrationModule", ["ngRoute", "ngResource"])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when("/ControlPanel/Users", {
templateUrl: "/templates/users/all.html",
controller: "userController"
});
$locationProvider.html5Mode(true);
});
user-controller.js
registrationModule.controller("UserController", function($scope, userRepository, $location) {
$scope.users = userRepository.get();
});
And last, the template: /templates/users/all.html
{{1+1}}
<table>
<tr><td>User Name</td></tr>
<tr ng-repeat="user in users">
<td>{{user.UserName}}</td>
</tr>
</table>
As mentioned, when I click on the Users link in the page, the whole page reloads and the template all.html is not loaded as I expect it.
#aaronfrost's comment made me re-check my javascript console more thoroughly and found that I need to include a
<base href="/" />
in the < head> tag of my document. Adding this causes everything to work.
Not sure, but the problem may be that you declared the controller as "UserController" with a capital "U", but in the routeProvider you specified it with a lowercase "u" as "userController".
I am guessing that you have an error in the console, so you might want to check there.
Change the routeProvider to use "UserController" instead of "userController" and it should work.

How to use data-ng-view in _layout.cshtml

I am trying to crate a MVC application with Angular. My application has common Header and footer. So I added it in _layout.cshtml. There are some static pages in the application. Hence I want to load this using Angular routing.
Here is my _layout.cshtml
<!DOCTYPE html>
<html data-ng-app="HappyHut">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header page-scroll">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse #bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Happy Hut", "Main", "Home", new { area = "" }, new { #class = "navbar-brand page-scroll" })
</div>
<div class="navbar-collapse collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>Contact Us</li>
<li>About Us</li>
<li>Login</li>
<li>Register</li>
<li>Test</li>
</ul>
</div>
</div>
</div>
<div class="container body-content" data-ng-view>
#RenderBody()
<hr />
<footer>
footer data
</footer>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
#Scripts.Render("~/bundles/Angular")
</body>
</html>
For testing purpose I have inserted some test html data in main.cshtml.
and here is my js file.
var HappyHut = angular.module("HappyHut", ['ngRoute']);
HappyHut.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$locationProvider.hashPrefix('!').html5Mode({
enabled: true,
requireBase: false
});
$routeProvider
.when('/ContactUs', {
templateUrl: 'Home/Contact'
})
.when('/AboutUs', {
templateUrl: 'Home/About'
})
.when('/Test', {
templateUrl: 'Home/Test'
});
}]);
Here the test.cshtml is like
#{
//Layout = null;
}
Hi Test
When I am loading Main.cshtml, the page gets loaded but body part gets hidden. If I click on Test, it gets loaded. However, if I add Layout = null, the same thing happens as Main.cshtml and a pop-up is opened which says
page is not running due a long running script
in the console it logs below error more than once for above issue
tried to load angular more than once
. Now I don't want to copy Header and footer in all the pages.
Can anybody please tell me how to proceed to make Main page content visible or all the pages which will be created using _layout.cshtml?
change the ng-view to ui-view and used 'ui.router' insted of ngroute,
alternative solution avaialble here
AngularJS Ui-Router with ASP.Net MVC RouteConfig. How does it work?

Creating a single page application using asp.net MVC4 and AngularJs

Hi, I am trying to create a single page application using AngularJs
and Asp.net MVC4. To start off, I tried to do basic navigation using
angular. I followed below steps.
Create MVC4 web application, Selected internet application,
Downloaded AngularJs libraries from Nuget,
Referenced it in Bundles.config file Gave reference of Angular in my
_layout.cshtml page,
Wrote app.js file for routing
Below is the code.
This is my bundles.config file
bundles.Add(new ScriptBundle("~/bundles/angular").Include(
"~/Scripts/angular.js",
"~/Scripts/angular.min.js",
"~/Scripts/angular-route.js",
"~/Scripts/angular-animate.js",
"~/Scripts/app/app.js",
"~/Scripts/app/js/controllers.js"));
This is my _Layout.cshtml file. As you can see I have used ng-app
directive to let html understand about angular.
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - My ASP.NET MVC Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body ng-app>
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("your logo here", "Index", "Home")</p>
</div>
<div class="float-right">
<section id="login">
#Html.Partial("_LoginPartial")
</section>
<div class="nav-collapse">
<nav>
<ul class="nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>Contact</li>
</ul>
</nav>
</div>
#*<div ng-view></div>*#
</div>
</div>
</header>
<div id="body">
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>
<div ng-view></div>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© #DateTime.Now.Year - My ASP.NET MVC Application</p>
</div>
</div>
</footer>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/angular")
#RenderSection("scripts", required: false)
<script src="~/app/app.js"></script>
<script src="~/app/js/controllers.js"></script>
</body>
</html>
This is my Index.cshtml file
#{ViewBag.Title = "Home Page";}
<h1>Angular Tutorial</h1>
<p>This is an online searchable database for food and nutrition information.</p>
<h3>We suggest the following:</h3>
I did routing in app.js file which is as follows
'use strict';
angular.module('myApp', [
'myApp.controllers',
'ngRoute'
]).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/Home/Contact', { templateUrl: 'Views/Home/Angular.html', controller: 'MyCtrl1' });
$routeProvider.otherwise({ redirectTo: '/Home/About' });
}]);
And last this is my controller. I have written an alert message to
check if angular is working.
'use strict';
angular.module('myApp.controllers', [])
.controller('MyCtrl1', function ($scope) {
alert('Hello from partial One');
});
I don't know what is it that I am doing wrong. I tried several
tutorials but could not make it SPA. Please help me. I really want to
solve this now. This is getting on my nerves now. Thanks a lot in
advance.
Using Angular and MVC is actually using two MV* frameworks at the same time.
My suggestion is to pick one and use it. Don't try to use both at the same time as it will just conflict with each other and get you more confused.
Since you're wanting to create a SPA, then your choice should be Angular. ASP.NET/MVC4 isn't going to give your a SPA, but it can give you a full-featured website.
Plan out what you want first, then pick the technology to get yourself there. Don't pick the technology first.
You're including angular.js and angular.min.js. That could be the issue...nothing else immediately jumps out at me.
I see a couple of problems:
your including angular.js and angular.min.js in the same bundle:
The bundle minimizes the js files automatically when your not in "optimization" or "debug" mode, so dont reference them at all.
Your using multiple ng-app tags and I didn't really see a good reason for that:
Each application has one ng-app="".
Your mixing up two different concepts(asp.net razor views + angular js):
You need to do this smart and gently. If you want to gain razor's strength for using html helpers\bundles etc. then that's ok only if your sure you know what your doing. How are you going to bind data to your models? I think that you should change you concept and work with asp.net web api instead and use angular "the right way" without mixing stuff up.
If you don't need anything more than a basic page with some Angular, in Visual Studio, just create an 'ASP.NET Empty Web Application' then add the Angular packages you need, an html file and a JavaScript file and off you go. I did this recently while learning angular and made a simple image carousel with basic navigation. If it helps you out at all, I have GitHub repo with my solution:
git clone https://github.com/antonosmond/AngularCarousel
It should give you an idea of how to get started with Angular JS and Visual Studio, without all the complexities of trying to integrate Angular into an MVC app.

Resources