Angular 2 wrong path for system.import('app') - asp.net-mvc

I have a project asp.net-mvc with angular2 element. Use to start the iis application, that start index.cshtml in the Home folder (initiated from the home controller). So, I modified for angular, as follows, the index file:
<!DOCTYPE html>
<html>
<head>
<title>Angular QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="~/styles.css" rel="stylesheet" />
<!-- Polyfill(s) for older browsers -->
<script src="~/node_modules/core-js/client/shim.min.js"></script>
<script src="~/node_modules/zone.js/dist/zone.js"></script>
<script src="~/node_modules/reflect-metadata/Reflect.js"></script>
<script src="~/node_modules/systemjs/dist/system.src.js"></script>
<script src="~/systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading AppComponent content here ...</my-app>
</body>
</html>
Now, when i start the application System.import('app') don't find app folder because do this request:
zone.js:1382 GET http://localhost/app/main.js 404 (Not Found)
however if I manually call the home controller, correctly displays the path:
http://localhost/my_virtual_path/app/main.js
Why this behavior?
I can change the system.import so that see the path relative to the project level?
for completeness, this is the system.config.js :
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
// librerie di terze parti
'angular2-datatable': 'npm:angular2-datatable',
'lodash': 'npm:lodash/lodash.js',
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular2-datatable': {
main: 'index.js',
defaultExtension: 'js'
},
}
});
})(this);

First of all I strongly suggest you don't use asp.net mvc or something like that for angular app. No need it. You can use it just as rest service (asp.net web api). Anyway, I think this problem comes from application path (IIS application)
So you need add this tag to html file head:
<head>
<base href="/my_virtual_path/">
.....

Related

How can I pass a Controller in as a dependency?

I'm looking to create a test file (test.js). The Test.js file's purpose will be to perform unit tests for a particular controller (ie: Main.controller.js).
How can I load in this controller to an external js file?
I've tried using sap.require:
sap.ui.require(["/pricingTool/Controller/Main.controller"],
function(Main){
//Quint code
test("hello test", function(assert) {
assert.ok(1 == "1", "Passed!");
});
});
But I get an error that says:
failed to load /Controller/Main.controller.js
This tells me I'm either structuring this wrong, using the wrong path, or both. Any suggestions would be helpful. I've attached my file tree below for reference.
Component.js
sap.ui.define(['sap/ui/core/UIComponent'],
function(UIComponent) {
"use strict";
var Component = UIComponent.extend("pricingTool.Component", {
metadata : {
metadata : {
maniest: "json"
},
rootView : "pricingTool.view.Main",
dependencies : {
libs : [
"sap.m",
"sap.ui.layout"
]
},
config : {
sample : {
files : [
"Main.view.xml",
"Main.controller.js"
]
}
}
},
init : function () {
// call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
// additional initialization can be done here
}
});
return Component;
});
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>Pricing Tool</title>
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.m"
data-sap-ui-theme="sap_belize"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-preload="async"
data-sap-ui-compatVersion="edge"
data-sap-ui-resourceroots='{"pricingTool": "./"}'>
</script>
<script src='../pdfmake-master/build/pdfmake.min.js'></script>
<script src='../pdfmake-master/build/vfs_fonts.js'></script>
<!-- Application launch configuration -->
<script>
sap.ui.getCore().attachInit(function() {
new sap.m.App ({
pages: [
new sap.m.Page({
title: "Pricing Tool Rapid Prototype",
enableScrolling : true,
content: [ new sap.ui.core.ComponentContainer({
name : "pricingTool"
})]
})
]
}).placeAt("content");
});
</script>
</head>
<!-- UI Content -->
<body class="sapUiBody" id="content" role="application">
</body>
</html>
initialTest.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Example</title>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.15.0.css">
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js">
</script>
<script src="//code.jquery.com/qunit/qunit-1.15.0.js"></script>
<script src="allTests.js"></script>
<script src="/Controller/Main.controller.js"></script>
<script>
</script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>
You do not need to reference the controller file directly inside the .html file.
The problem is that UI5 does not know where to find your resources. The resolution process is the following:
All standard resources are loaded from a path relative to where your sap-ui-core.js was loaded from.
All resources with custom namespaces are loaded based on the resource roots definition.
Basically, in the resource roots you define a map between a namespace prefix and the location where to find the resources starting with that prefix. If you use relative paths, then the locations are resolved relative to your html file.
In your index.html you have done this: data-sap-ui-resourceroots='{"pricingTool": "./"}' which is perfectly fine. Because your index.thml is located at the root of the project, requesting the pricingTool/Controller/Main.controller will lead to making a request at ./Controller/Main.controller which is actually our file.
But in your initialTest.html you failed to specify any resource root at all. Moreover, you referenced your controller directly and the path seems to not be right (note that a path starting with a leading / is considered an absolute path on the current host; depending on the server you are using, this might not be correct, as usually each application has its own subpath in the server).
You should therefore include a data-sap-ui-resourceroots='{"pricingTool": "../"}' inside your initialTest.html. Notice that I have used .. because the html file is inside the Test folder (and the other stuff is in sibling folders).

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']);
});

Unittest polymer.dart with karma

The problem is polymer is not loading. Karma has filters for the files it loads, I'm trying load and initialize polymer to be able to test polymer elements with no success (outside the test environment the code works fine).
Debugging the code in the browser I don't see the polymer.html loaded, and besides the custom element is in the page, they do not have the properties and behavior, and don't have the shadow dom.
What I try to do:
karma.conf.js
/**
* Compile HTML into JS so that they can be used as templates
*/
preprocessors: {
'packages/**/*.html': 'html2js'
},
basePath: '.',
frameworks: ['dart-unittest'],
// list of files / patterns to load in the browser
// all tests must be 'included', but all other libraries must be 'served' and
// optionally 'watched' only.
files: [
'test/*.dart',
{pattern: '**/*.dart', watched: true, included: false, served: true},
'packages/browser/dart.js',
{pattern: 'scripts/**/*.js', included: false},
{pattern: '**/*.html', included: false, served: true},
'packages/polymer/polymer.html'
],
autoWatch: true,
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 5000,
plugins: [
'karma-dart'
]
test_index.html
<!DOCTYPE html>
<html>
<head>
<title>Run Unit Tests</title>
<link rel="import" href="packages/polymer/polymer.html" />
<link rel="import" href="packages/vader/components/window.html" />
</head>
<body>
<script type="text/javascript" src="packages/unittest/test_controller.js"></script>
<script type="application/dart;component=1" src="test_vader_browser.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
test_vader_browser.dart
import 'package:scheduled_test/scheduled_test.dart';
import 'vader/_vader.dart' as vader;
import 'package:polymer/polymer.dart';
#initMethod
main() {
setUp((){
schedule(() => Polymer.onReady);
});
groupSep = ' - ';
vader.runAllTests();
}

Can't get ng-controller to work in ionic app

edit: This questions is solved
Stupidly enough, the url /img/images.json is treated differently by the simpleHttpServer used to test the application than by the iOS simulator.
It was a long search why it would show the list in the browser when testing but not in the simulator. Apparently the simpleHttpServer that comes with python will treat a url starting with the / as it's root, for example the www folder. The simulator does not and would appreciate a relative location, starting with no /
The problem seems mostly caused by the rustiness of my web-dev skills ^.^
====================
I am trying to make a simple ionic app, and for some input I am using the Angular Tutorial.
I have a very simple page that should load the contents of a json-file with image data. And all it needs to do for now is showing the image names. At the end it should dump the complete data from the json-file.
This is all based of the blank project created with ionic.
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controller.js"></script>
</head>
<body ng-app="phocalsApp">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Ionic Blank Starter</h1>
</ion-header-bar>
<ion-content ng-controller="imageListCtl">
<ul class="imagelist">
<li ng-repeat="image in imagelist" >
{{image.imgName}}
</li>
</ul>
{{imagelist | json}}
</ion-content>
</ion-pane>
</body>
</html>
app.js:
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('phocalsApp', ['ionic', 'phocalsControllers'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
controller.js
'use strict';
var phocalsControllers = angular.module('phocalsControllers', []);
phocalsControllers.controller('imageListCtl', ['$scope', '$http',
function($scope, $http) {
$http.get('/img/images.json').success(function(data) {
$scope.imagelist = data;
});
$scope.orderProp = 'imgDate';
}]);
images.json:
[
{
"imgUrl":"",
"imgName":"Nieuwste Foto",
"imgDate":20140525
},
{
"imgUrl":"",
"imgName":"tweede Foto",
"imgDate":20140524
},
{
"imgUrl":"",
"imgName":"derde Foto",
"imgDate":20140523
}
]
Seeing as I pretty much use the same code as the angular example, I would expect this to work, unfortunately all the output I am getting when running in the ios Simulator is an empty page with the header-bar. No errors or nothing. Can anyone tell me what I am doing wrong here?
You are missing some console.log(data) in your controller to check whether the controller is initialized, wether $http actually succeeds etc.
Even after using angular for months, i have to log every step cause there are too many things to go wrong :)
Also you should add an error function to
$http.get('/img/images.json').success(function(data) {
$scope.imagelist = data;
}).error(function(data) ....;

phonegap + jquery mobile, good practices

until now I was not using this index.js that Phonegap recommends :
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicity call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
};
Where should I put my own js functions and events (all my js file), into this, out of this, in another file ?
Where should I call those js files and where should I call the app.initialize, in relation to the position of the calls to the js files ?
Here's my html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="height=device-height,width=device-width,initial-scale=1.0,maximum-scale=1.0">
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.css" type="text/css" media="all" />
<link rel="stylesheet" href="css/style.css" type="text/css" media="all" />
<script src="js/jquery-1.9.1.js"></script>
<script src="js/index.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
<script src="js/jquery.mobile.config.js"></script>
<script src="js/jquery.mobile-1.3.2.js"></script>
<script src="js/jquery-geturlvar.js"></script>
<script src="js/boardDims.js"></script>
<script src="js/functions.js"></script>
<!-- <script src="cordova.js"></script>-->
</head>
<body>
For now I am compiling using the remote service : $ phonegap remote run android
It would be really useful to have a default template of an app using Phonegap + JQM, for beginners like me ;-)
That index.js is included as an example, you don't really need to use it. It is basically showing you how to work with ondeviceready. You need to use ondeviceready when you work with plugins, since most of their calls will only be available after ondeviceready has been fired. So you hook up your calls to plugins on a listener to ondeviceready. I am doing it like this for instance:
<script type="text/javascript">
function onLoad() {
document.addEventListener("deviceready", MYAPP.events.onDeviceReady, false);
}
</script>
</head>
<body onload="onLoad();">
And inside MYAPP.events.onDeviceReady I do the calls to geolocation, camera, or whatever plugin I'm working with.
BTW, two important things to notice in you example: You need to include cordova.js before you can access ondeviceready or work with any plugin, plus you are including index.js twice. Perhaps you duplicated the <script src="js/index.js"></script> to edit it and include js/cordova.js and forgot to change the name/path?
Apart from that, what I do is separating the app's JS and the external libs in two separate directories for better organisation, like "lib" and "js", so you would include "js/functions.js" and "lib/jquery.js".
I include both the libs and custom JS files at the bottom of the body tag for a slight better performance: Where should I put <script> tags in HTML markup?
And I name the files under "js" (custom JS files for the app) according to their purpose/content, like: events.js, models.js, settings.js, util.js, ... You can see in the snippet above that I have "namespaced" my custom JS objects under the capitalised name of the app, so everything in util.js will be called like: MYAPP.util.formatDate().

Resources