AngularJS 2 influenced by URL in ASP.NET MVC - asp.net-mvc

I'm using AngularJS 2 in a ASP.NET MVC 5 project, I do not use the routing provided by Angular and rely only on the MVC routing strategy.
Strangely, AngularJS seems to look at the URL and only load correctly when I'm on a route "domain/Controller", if I'm on a route as "domain/Controller/" or "domain/Controller/Action" my Angular app is not loading and I have the following error in the browser:
I'm using the following script to load my bootstrapper:
<script src="~/Scripts/systemjs.config.js"></script>
<script>
System.import('../tsScripts/boot').catch(function (err) {
console.error(err);
});
</script>
my boot.ts file:
///<reference path="./../typings/globals/core-js/index.d.ts"/>
import {bootstrap} from '#angular/platform-browser-dynamic';
import {HTTP_PROVIDERS} from '#angular/http';
import {AppComponent} from './app';
bootstrap(AppComponent, [HTTP_PROVIDERS]);
I have no idea why Angular (or another part coming with the framework) is incompatible with the MVC routing, or what is wrong with my implementation.

I ran into the same problem,
and I simply solved it placing this code into the head tag of _Layout.cshtml (so that is applied to all views)
<head>
<base href="/">
...
</head>
Angular official doc
You can also fix it this way
import {APP_BASE_HREF} from '#angular/common';
#NgModule({
...
imports: [RouterModule],
providers: [{provide: APP_BASE_HREF, useValue : '/' }]
]);

Related

Angular inside existing .NET Core MVC solution not working

I got an existing solution in .NET Core MVC that I wanted to use Angular in a specific view, but not everywhere.
Therefore I used the command line to create a new Angular application inside the solution in a folder called Angular.
The structure is:
SelfService (Project)
Angular
src (all other angular structure here also in this level)
Views
Dashboard
Dashboard.cshtml
There is a feature switch to let it be eased in by pilots trying it out.
I use the feature of proxy because Angular development server is running port 4200, and my applications port is running port 44323. So using proxy to fix that on my local machine.
I have set it up, which works very well when running the development server and going to "http://localhost:4200", but when I go to /dashboard in the existing solution it loads the same view, but the clicks and updates doesn't work. It simply does nothing
Startup.cs (Part of)
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "Angular/dist";
});
}
public void Configure
{
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Default}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Angular";
if (env.IsDevelopment())
{
spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
}
// Doesn't work so using a bat-file running ng serve and then works
//if (env.IsDevelopment())
//{
// spa.UseAngularCliServer(npmScript: "start");
//}
});
}
Dashboard.cshtml
#if (ViewBag.IsAngularDasboardFeaturesEnabled)
{
<app-root>app-root is loading ...</app-root>
}
.....
#section EndContent {
#if (ViewBag.IsAngularDasboardFeaturesEnabled)
{
#if (hostingEnv.IsDevelopment())
{
<script type="text/javascript" src="http://localhost:4200/runtime.js"></script>
<script type="text/javascript" src="http://localhost:4200/polyfills.js"></script>
<script type="text/javascript" src="http://localhost:4200/styles.js"></script>
<script type="text/javascript" src="http://localhost:4200/vendor.js"></script>
<script type="text/javascript" src="http://localhost:4200/main.js"></script>
}
else
{
<script type="text/javascript" src="~/scripts/AngularOutput/main.js" asp-append-version="true"></script>
<script type="text/javascript" src="~/scripts/AngularOutput/polyfills.js" asp-append-version="true"></script>
<script type="text/javascript" src="~/scripts/AngularOutput/runtime.js" asp-append-version="true"></script>
<script type="text/javascript" src="~/scripts/AngularOutput/styles.js" asp-append-version="true"></script>
<script type="text/javascript" src="~/scripts/AngularOutput/vendor.js" asp-append-version="true"></script>
}
}
app.component.html
<div (click)="clickHandler()">
{{title}}
</div>
app.component.ts
export class AppComponent {
counter: number = 1;
title = 'Angular LAWE (You are the BOSSmann)' + this.counter;
constructor() {
setTimeout(() => {
console.log("hello");
this.title = "something else";
}, 5000);
}
clickHandler(): any {
console.log("Change click", ++this.counter);
this.title = "hi" + this.counter;
}
}
I would expect that when it works in with the development server for http://localhost:4200, then it would also work for https://localhost:44323/dashboard/ but it doesn't.
?? Can it be the problem of https vs http?
UPDATE 1: I have used in Angular application folder in package.json "start": "ng serve --ssl true", which removed the WDS-error, but now gives GET https://localhost/runtime.js net::ERR_CONNECTION_REFUSED
?? When my development server from VS in Startup.cs doesn't work, could that be the reason why the clicks and everything doesn't work? It renders the component, and writes logs from init, and I can call the clickMethod that logs clicked, but clicking the div doesn't work.
UPDATE 2: Changed the port to be the local developments port instead of 4200, but gave a 500 response instead.
I found out that if I copied the markup to another controller and another view everything worked out fine.
It was the combination of Knockout mixed with Angular that made it not work.
<!-- ko if: selectedAreaTabFound() === 1 -->
<app-root>app-root is loading ...</app-root>
<!-- /ko -->
So the click events was working if it wasn't combined with Knockout, and routing and all events could fire if it was in a new page.
Eventually I scraped everything away and it came down to removing all the knockout comments around it for it to work.
So now I have to think about another way to make it work where I wanted it, but I found the problem.

Angular2 http service not found

cant get a simple http service to work in angular2. I just get 404 on the service for some reason. It does not contain any functionality yet, but I seems that the DI does not work.
As soon as I add TestService when bootstrapping the application i get the following. GET http://127.0.0.1:8080/testService 404 (Not Found)
index.html
<!DOCTYPE html>
<html lang="en-GB">
<head>
<title>AngularJS 2 Tutorial Series</title>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/angular2.dev.js"></script>
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true }
});
System.import('./app/app.ts');
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>
app.ts
import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core';
import {Injectable} from 'angular2/core'
import {TestService} from 'testService';
#Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>',
})
class AppComponent {
}
bootstrap(AppComponent, [TestService]);
TestService.ts
import {Http} from 'angular2/http';
import {Injectable} from 'angular2/core';
#Injectable()
export class TestService {
constructor(public http: Http){
}
}
I just ran into this, fixed it by adding the script reference to the http bundle:
<script src="node_modules/angular2/bundles/http.dev.js"></script>
Tried it after remembering that I added a similar resource after implementing routing. Hope this helps someone else!
This is because by Default your 'http.dev.js' is not sourced
Step 1 : index.html
Include 'http.dev.js'
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>
Step 2: main.ts
Add import and add 'HTTP_PROVIDERS'
import {bootstrap} from 'angular2/platform/browser';
import { HTTP_PROVIDERS } from 'angular2/http';
import {AppComponent} from './app.component';
bootstrap(AppComponent, [HTTP_PROVIDERS]);
STEP: 3 app.component.ts
import Http and use it
import {Http} from 'angular2/http';
constructor(http: Http) {
http.get('http://jsonplaceholder.typicode.com/posts/1').subscribe((data) => {
this.response = data._body;
})
}
You will need to add Http by supplying it as a provider. There are 2 ways to accomplish this:
1) at a global level you can specify when you bootstrap the application:
bootstrap(AppComponent, [TestService, Http]);
2) inside the component you are trying to use it within:
#Component({
...
providers: [Http]
})
public class ...
NOTE you will also have to import/require Http when you are supplying it as a provider. This will allow angular's DI to discern what will be injected.

Running Normal Dart HTML and Angular Dart 2 in the same app

Is it possible to mix a normal Dart HTML application with Angular Dart 2 and have Angular Dart 2 run in certain parts of the application and not other parts?
I've attempted that, but it seems Angular is injecting itself into every page.
index1.html:
<script type="application/dart" src="main.dart"></script>
<script data-pub-inline src="packages/browser/dart.js"></script>
</body>
index2.html:
<my-app>Loading...</my-app>
<script async src="main2.dart" type="application/dart"></script>
<script async src="packages/browser/dart.js"></script>
</body>
main.dart:
// many imports
void main() {
// manual code to hook urls, html etc
}
main2.dart:
import 'package:angular2/angular2.dart';
import 'package:angular2/bootstrap.dart';
#Component(selector: 'my-app', template: '<h1>Testing Angular Dart 2</h1>')
class AppComponent {}
main() {
bootstrap(AppComponent);
}
pubspec.yaml:
...
environment:
sdk: '>=1.0.0 <2.0.0'
dependencies:
...
less_dart: any
browser: any
http: any
event_bus: any
dart_to_js_script_rewriter: any
angular2: 2.0.0-beta.0
transformers:
- dart_to_js_script_rewriter
- $dart2js:
commandLineOptions: [--enable-experimental-mirrors]
- less_dart:
entry_points: [web/styles/main.less, web/styles/test.less]
build_mode: dart
- angular2:
entry_points: web/main2.dart
The angular2 transformer is clearly pointing at main2.dart and only index2.html is importing main2.dart, but when I load index1.html which is importing main.dart, the angular app runs.
Is it possible to do what I want to do or is it a case of all-or-nothing when including Angular Dart 2?
What do you mean by "it seems Angular is injecting itself into every page."? If you have different entry points (index1.html, index2.html, ...) each entry point is an individual application and for each you can enable Angular or not. If this doesn't work it's a bug in some transformer.

Typescript AMD and AngularJs - Failed to instantiate module

I'm unsing TypeScript AMD (RequireJs) and AngularJs.
I want to use AMD for my typescript code and not for the rest: jquery, angular, bootstrap, ...
For thirdparty js I'm using MVC bundling and I want to continue this way.
This is my thirdparty bundle config:
bundles.Add(new ScriptBundle("~/bundles/thirdparty").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js",
"~/Scripts/require.js",
"~/Scripts/angular.js",
"~/Scripts/angular-route.js"
));
My _Layout.cshtml is something like:
<!DOCTYPE html>
<html ng-app="PafBase">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
#Scripts.Render("~/bundles/thirdparty")
<script>
require.config({
baseUrl: 'typescript/'
});
require(['module/BaseApplication']);
</script>
</head>
<body>
#RenderBody()
</body>
BaseApplication.ts is something like:
var app: ng.IModule = angular.module('PafBase', ['ngRoute']); // Breakpoint here ****
app.config(['$routeProvider', ($routeProvider) => { ... }]);
When run the application I get this javascript error:
[$injector:modulerr] Failed to instantiate module PafBase due to:
Error: [$injector:nomod] Module 'PafBase' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
If I continue the execution I can see that BaseApplication.ts is executed after the angular error.
I think it can be due to angular scan the DOM after ready and found <html ng-app="PafBase"> then search "PafBase" module and not find it due to requireJs don't load BaseApplication.ts before angular scan the DOM.
How to do angular scan the dom after my code is executed?
You can manually bootstrap Angular instead of specifying ng-app="PafBase". Take a look at the docs here: https://docs.angularjs.org/guide/bootstrap
Basically you just need to remove ng-app from your html and add this to your JS
angular.element(document).ready(function() {
angular.bootstrap(document, ['PafBase']);
});

AngularDART component

I made the below simple code while learning AngularDART Component, but nothing is displayed, can anyone help me knowing what mistake I made:
my html main file:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="bootstrap.css">
<link rel="stylesheet" href="main.css">
<title>AngularDART training</title>
<script type="application/dart" src="main.dart"></script>
<script src="packages/browser/dart.js"></script>
</head>
<body ng-app>
<h1 id='text_id'>Welcome</h1>
<the-component></the-component>
</body>
</html>
the main.dart file is:
import 'package:angular/angular.dart';
import 'package:angular/application_factory.dart';
#Component(
selector: 'the-component',
templateUrl: 'angularComponent.html',
cssUrl: 'angularComponent.css',
publishAs: 'cmp')
class myComponent {var name = 'Component';}
main() {
var module = new Module()
..bind(myComponent);
applicationFactory().addModule(module).run();
}
the angularComponent.html file is:
<p>This is the angular: {{cmp.name}}</p>
the <the-component></the-component> is not working, and not displaying anything!
thanks
Angular transformer picks the components from the lib folder. If you place your component's files (.dart, .html, .css) in other folders (i.e. web), you need to specify them in the transformers section of pubspec.yaml.
For example,
transformers
- angular:
-html_files:
- absolute/path/to/your/html
Hope this works for you.
Thanks for all who tried to help, the solution was writing the pubspec.yaml as:
dependencies:
angular: '>=0.12.0 <0.13.0'
transformers:
- angular: {html_files: "web/angularComponent.html"}
Thanks.
The bug is that your pubspec.yaml doesn't list angularComponent.html as an asset.
The Angular transformer which creates the StaticClosureMap did not parse the template, never saw the cmp.name expression and never generated a getter.
We should have given you a better error message. If you still have the complete project isolated well, please file a bug on the Github project and we can make this experience better.

Resources