I'm using angular 1.5 and webpack to generate a dist folder with my angular aplication.
This is my folder structure:
--app
--dist
--loginComponent
--login.html
--homeComponent
--home.html
...
--app.css
--app.js
--index.html
And this is my index.html:
<!doctype html>
<html lang="es" ng-app="firmaDigitalApp" ng-strict-di>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="dist/app.css">
<script src="dist/app.js"></script>
</head>
<body>
<app></app>
</body>
</html>
Everything good so far, the problem is that app.js generated is not accessing the html by its path in a relative manner so it can't find the resource (instead of looking for home.html in context/dist/homeComponent.html, it's looking for it in context/homeComponent.html).
Just in case, this is homeModule.js:
require('./administradorComponent/administradorModule.js');
require('./definicionComponent/definicionModule.js');
var controller = require('./homeController');
var homeModule = angular.module('homeModule', [ 'administradorModule', 'definicionModule' ]);
homeModule.component('homeComponent',
{
templateUrl : 'homeComponent/home.html',
$routeConfig : [
{
path : '/administrador/...',
name : 'Administrador',
component : 'administradorComponent',
useAsDefault : true
}]
});
homeModule.controller('homeController', [ '$rootScope', '$location', '$log', controller ]);
What can I do so my angular application resources use relative paths to access each other so I don't have to type dist/ over and over again?
Let me know if you need more information.
Rather than using templateUrl, I'd recommend using html-loader to make your templates be built into your output file (i.e. app.js). If you set that up, you can just do:
template: require("homeComponent/home.html") // Resolves to a string
This will cause your bundle to take a little longer to download up front, as all the templates will get loaded too, but you won't have to wait for the templates to load asynchronously when the component is initialized, so it evens out in my opinion.
Related
Context
I'm writing an application with Electron and Angular 2+ using Angular CLI. I've set up my electron .js file to point to the URL provided by the ng serve command, that usually is localhost:4200, in order to capture the code changes. Some considerations:
The address localhost:4200 points to index.html;
index.js is my Electron entry point script
Here is my index.js file used as an entry point for the electron module.
const {app, BrowserWindow} = require('electron');
const url = require('url');
const path = require('path');
let win = null;
function createWindow() {
win = new BrowserWindow({width: 1000, height: 600, show: false});
win.loadURL('http://localhost:4200');
win.maximize();
win.on('closed', () => {
win = null;
});
win.on('ready-to-show', () => {
win.show();
});
win.webContents.openDevTools();
}
app.on('ready', () => {
createWindow();
});
app.on('activate', () => {
if (win === null) {
createWindow();
}
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
And my index.html file:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>BRISA Carbon</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<!--Clarity Design Elements-->
<link rel="stylesheet" href="../node_modules/clarity-icons/clarity-icons.min.css">
<script type="text/javascript" src="../node_modules/#webcomponents/custom-elements/custom-elements.min.js"></script>
<script type="text/javascript" src="../node_modules/clarity-icons/clarity-icons.min.js"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
My Problem
When I run ng serve, the node_modules resources inside the .html file are not being loaded and the Chrome console outputs the following messages
I know that the path to the resources are correct because I'm using WebStorm IDE and I can go to the referenced element through a link like this image below.
Why my resources are not being loaded when I'm running in Angular live mode?
For everyone that is having this same problem, I just found a solution. Instead of loading my resources through the index.html file, I've placed them in the .angular-cli.json. Basically, Angular 2+ has the own way of importing resources and seems that is not correct loading resources from the main .html file.
Well, for scripts (I mean, .js files), I'm placing it in the scripts array and styles inside the styles array. The .angular-cli.json file section that I've changed looks like this:
"styles": [
"styles.css",
"../node_modules/clarity-icons/clarity-icons.min.css",
"../node_modules/clarity-ui/clarity-ui.min.css"
],
"scripts": [
"../node_modules/#webcomponents/custom-elements/custom-elements.min.js",
"../node_modules/clarity-icons/clarity-icons.min.js"
]
Hope that this information will help someone else. For me everything is working just fine.
I assume you're experiencing the same problem when you're visiting localhost:4200 in your browser also?
In your index.html you're referencing to ../node_modules/ ... which works in your IDE because that's how the folder structure looks like.
Let's say your folder structure looks like this:
node_modules/
src/
And src is the folder that your server's using as root. Then the server wont be able to retrieve files from .. (since a root dir has no parent dir).
Instead of referencing to the JS files in your index.html, you should import/require them in your other JS files. Exactly how you do that depnds on your building/bundling tools (eg Webpack and/or Babel).
import '#webcomponents/custom-elements/custom-elements.min.js'
import 'clarity-icons/clarity-icons.min.js'
import 'clarity-icons/clarity-icons.min.css' // Assumes that you use webpack and webpack-css-loader, for example
I just got started with Foundation for Apps, but I was having trouble adding my angular controllers in a separate folder and using them.
I have this current structure in my assets' js folder:
js/
app.js //this has all the controllers etc. by chaining
but I want it to be
js/
app.js
controllers/
home.controller.js
main.controller.js
I don't want to keep a single large js file developed by chaining my controllers, services etc. I want a more modular structure as specified.
When I changed it to the modular structure, I got following three errors:
1. 'HomeCtrl' not defined.
2. Uncaught SyntaxError: Unexpected token < at the 1st line of home.controller.js
3. Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:8079/assets/js/home.controller.js". at the point where I am including 'home.controller.js' in index.html
Here's my template:
---
name: home
url: /
controller: HomeCtrl
---
<div class="grid-container">
<h1>Welcome to Foundation for Apps!</h1>
<p class="lead">This is version <strong>1.1 Weisshorn</strong>.</p>
</div>
home.controller.js:
app.controller('HomeCtrl', ['$scope', function($scope) {
$scope.temp = 'hello';
}]);
app.js:
var app = angular.module('application', [
'ui.router',
'ngAnimate',
'foundation',
'foundation.dynamicRouting',
'foundation.dynamicRouting.animations'
])
.config(config)
.run(run)
;
config.$inject = ['$urlRouterProvider', '$locationProvider'];
function config($urlProvider, $locationProvider) {
$urlProvider.otherwise('/');
$locationProvider.html5Mode({
enabled:false,
requireBase: false
});
}
function run() {
FastClick.attach(document.body);
}
To solve this I tried adding my controller reference in gulpfile.js by referring this
I also referred this but I still cannot get it to work. Any idea what I am doing wrong?
Inside gulpfile.js check this line. You'll see that only client/assets/js/app.js is used when coupling your minimized file. You need to make it copy all your controller's .js files too :
// These files are for your app's JavaScript
appJS: [
'client/assets/js/app.js',
'./client/assets/js/controllers/*.js',
]
You can also use an angular module to hold all your controllers & services then injecting it to your app module. This is how I'm using it here and this is how it is also done in this great ready to use Fork : https://github.com/CreativityKills/foundation-apps-template
Note: remember to restart gulp after each modify of its config file and check if your code has been well included in the built JS file ( by default is /build/assets/js/app.js )
There is something really weird going on when I'm using RequireJS with AngularJS. I managed to load all my angular dependencies through RequireJS. I can see those scripts downloaded when I open up the Sources pane in Chrome's developer tool. But Angular keeps throwing an error in the console that it failed to instantiate the module:
Uncaught Error: [$injector:modulerr] Failed to instantiate module MyTestApp due to:
Error: [$injector:nomod] Module 'MyTestApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure...<omitted>...0)
It seems like Angular, when loaded with RequireJS, cannot bind with the ng-app tag in the HTML page. I'm not sure if this is the case but it seems like so to me because when I import angular.min.js manually into the HTML page, it all works fine.
Did I do anything wrong when using RequireJS with Angular? How should I use the two together? Here's how my code look:
index.html
<!doctype html>
<html lang="en" ng-app="MyTestApp">
<head>
<meta charset="utf-8">
<title>AngularJS</title>
<link rel="stylesheet" href="css/style.css"/>
<script data-main="main" src="js/require.js"></script>
</head>
<body>
<div ng-controller="TestController">{{helloMessage}}</div>
</body>
</html>
main.js
require.config({
baseUrl: "scripts/app",
shim: {
"angular": {
exports: "angular"
},
"angular.route": {
deps: ["angular"]
},
"bootstrapper": {
deps: ["angular", "angular.route"]
},
},
paths: {
"angular": "../angular",
"angular.route": "../angular-route",
"bootstrapper": "bootstrapper"
}
});
require(["angular", "angular.route", "bootstrapper"],
(angular, ngRoute, bootstrapper) => {
bootstrapper.start();
}
);
bootstrapper.js
function run() {
app = angular.module("MyTestApp", ["ngRoute"]);
app.controller("TestController", TestController);
console.log(app); //Prints object to console correctly, ie, angular was loaded.
}
Here is how I would do it (DEMO).
In main.js, require angular, your app and maybe a controllers.js and other files:
require(['angular', 'app'], function (app) {
angular.element(document).ready(function () {
angular.bootstrap(document, ['MyTestApp']);
});
});
In app.js, require angular and angular route:
define(['angular', 'angular.route'], function() {
var app = angular.module("MyTestApp", ["ngRoute"]);
return app;
});
This is manual bootstraping and therefore does not need the ng-app tag at all.
I'm currently working on a pretty big application with angular and requirejs and I prefer to load the "big" libraries that are used by the whole app anyway independently from requirejs.
So I load one big file which includes angular, angular-route, requirejs, main.js in the beginning. Or if it makes sense to use a CDN version, load it from there. On the other hand I load every controller, directive, filter and service on request. I currently have 50+ controllers which allready makes a difference in initial load time.
But that all depends on the size of your app.
First you does not need to get a variable from the load of "angular.route". The module will be directly loaded in angular.
I think you should also wait for the dom ready event and also make a requirejs app module that will be in charge of loading all app dependencies:
app/app.js:
define([
"angular",
"angular-route",
"app/controllers",
"app/directives",
[...]
], function(angular){
var app = angular.module('app', [
"ngRoute",
"app.controllers",
"app.directives",
[...]
])
.config([function(){
// app configuration goes here
}]);
return app;
})
main.js
require(["angular", "app/app"],
function (angular, app){
angular.element(document).ready(function() {
angular.bootstrap(document, [app.name]);
});
}
);
In my Sencha application I have a Config.js file containing some service URLs:
Ext.define('MyApp.utils.Config', {
singleton : true,
config : {
authBaseUrl : '...',
serviceBaseUrl : '...',
reportsBaseUrl : '...',
imagesUrl : '...'
},
constructor : function (config) {
this.initConfig(config);
}
});
Before deployment I use the
sencha app build
command from the Sencha Touch SDK to minify and concatenate files etc.
My problem is that the build process will also add config.js to the minified app.js file, although it would be very useful if I could edit it without the need of rebuilding / redeploying the whole application. I haven't found any means to change the behaviour of the build process.
So after building the application I would like to have these three js files:
sdk/sencha-touch.js (concatenated, minified, cached in localstorage after the first download)
app.js (concatenated, minified, cached in localstorage after the first download)
config.js (left untouched, without caching it in the localstorage)
Break it out from the app so that it isn't bundled, then put a reference to it in app.json, this has worked well for me in similar cases.
I also have a config.js that is repeatedly modified during my development, so in my app.json it would look like this:
"js": [
{
"path": "sdk/sencha-touch-all.js"
},
{
"path": "config.js"
},
{
"path": "app.js",
"bundle": true,
"update": "full"
}
],
This makes sure that your config.js file is included in the build.
Then you need to add the script to your app.html file, just make sure that it is loaded before your main app.js. Mine looks like this (autogenerated from Sencha Architect):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>llm</title>
<link rel="stylesheet" href="resources/css/llm.css">
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="sdk/sencha-touch-all.js"></script>
<script src="config.js"></script>
<script src="cordova-2.0.0.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body></body>
</html>
Hope that this helps you!
I have a project loaded using RequireJS and I would like to test the models.
I have the following test :
require(['../../js/models/lead_sharing'], function(Lead_sharing_Model) {
describe('when instantiated', function () {
it('should exhibit attributes', function() {
var test = new Lead_sharing_Model({
attribute : 3
});
expect(test.get('attribute')).toEqual(3);
});
});
});
But I have a error " failed with error: SyntaxError: Unexpected token"...
In reality , I don't know if it's possible to test a backbone/requireJs project with Jasmine. Indeed, how can I include my views/Models... without require config (like definition of the paths...)
Thanks you
Ps : just a small edit to specify that I would like test with a a js cmd. no in a browser. :)
It is certainly possible to test a backbone/requirejs project with jasmine. Pull the same require config used by the app into the html page that drives the unit tests. For example:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="vendor/jasmine.css">
</head>
<body>
<script src="vendor/jasmine.js"></script>
<script src="vendor/jasmine-html.js"></script>
<script src="../assets/js/libs/jquery.js"></script>
<script src="../assets/js/libs/underscore.js"></script>
<script src="../assets/js/libs/backbone.js"></script>
<!-- This points to the require config that is also used by the main app. -->
<script data-main="../app/config" src="../assets/js/libs/require.js"></script>
<script>
require({ paths: { spec: "../test/spec" } }, [
// Pull in all your modules containing unit tests here.
"spec/lead-sharing-specs"
], function() {
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
});
</script>
</body>
</html>
Since you want to run this outside of the browser, check out PhantomJS, grunt, and grunt-jasmine-task.