I'm currently developing a small educational project using HTML5, CSS, JS and AngularJS.
Problem: Loading of a AngularJS Directive in my index.html file
Error code [1] - Local browser
Error: Access to restricted URI denied
Some answers to this question, suggested to deploy the project on a web server. I did it and the error was very interesting:
Error code [2] - Webserver
Failed to load resource: the server responded with a status of 404 (Not Found)
File structure
app/
---- app.js
---- components/
---------- view1/
-------------- fullView.html
-------------- fullViewApp.js
-------------- partialViews/
------------------ partsOfFullView.html
------------------ morePartsOfFullView.html
assets/
---- libs/
---- css/
---- ...
---- ...
index.html
Code
index.html
<!DOCTYPE html>
<html ng-app="MyApp">
<head>
<meta charset="utf-8">
<title>My Example</title>
<!-- CSS -->
<link href="./assets/css/bootstrap.min.css" rel="stylesheet">
<link href="./assets/css/bootstrap-datetimepicker.min.css" rel="stylesheet">
<!-- Libs -->
<script src="./assets/libs/jquery-2.1.1.min.js"></script>
<script src="./assets/libs/angular.min.js"></script>
<script src="./assets/libs/bootstrap.min.js"></script>
<script src="./assets/libs/moment-with-locales.js"></script>
<script src="./assets/libs/bootstrap-datetimepicker.min.js"></script>
<!-- App's modules -->
<script type="text/javascript" src="./app/app.js"></script>
<script type="text/javascript" src="./app/components/view1/fullViewApp.js"></script>
</head>
<body ng-controller="MyAppTranslationCtrl">
<!-- my custom directive -->
<qwe></qwe>
</body>
</html>
app.js
angular.module('MyApp', ['MyApp.View1App'])
.controller('MyAppTranslationCtrl', function($scope) {
console.log('-> MyApp Translation example');
});
fullView.html
<div ng-app="MyApp.View1App" ng-controller="...">
<div ng-controller="...">
<!-- content, other directives, etc... -->
...
...
</div>
</div>
fullViewApp.js
angular.module('MyApp.View1App', [])
.directive('qwe', function() {
return {
restrict: 'E',
templateUrl: 'fullView.html'
}
});
Sorry for the long post, but I tried to make it clear, understandable and easier to find the problem.
After all I am stuck on this error and I can't get it fixed.
I have tried to move all the files in one folder and it magically works! But when I separate them in different folders = ERROR. I can't get it up and running!
Please assist me :)
############################ ANSWER
After changing the relative paths to have a full qualifier before them, as suggested in the next post, everything was fine!
Thank you!
Assuming this is throwing the error:
angular.module('MyApp.View1App', [])
.directive('qwe', function() {
return {
restrict: 'E',
templateUrl: 'fullView.html'
}
});
You need to use the full path.
angular.module('MyApp.View1App', [])
.directive('qwe', function() {
return {
restrict: 'E',
templateUrl: 'app/components/view1/fullView.html'
}
});
Related
I'm triying to add bootstrap ui modules to an angular project. In every tutorial I read that after download the module i'm supposed to add a directive (angular.module(for example: 'App', ['ui.carousel']) to certain file that in some forums i've read is called app.js. This file doesnt exist in my project. The question is: Should I create it? Where? Is a controller necesary? How is the flow that this must follow? Then I should add it to the index.html?
Getting advanced here with components without even knowing the basics. I recommend starting with just controllers (without components). But, here is a basic example of how scripts are added:
<!DOCTYPE html>
<html ng-app="myApp">
<!-- Adding scripts here. The order matters: angular.js first, then its dependancies, e.g. ui-bootstrap -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<body>
<div>
<!-- main body -->
<div>
<hello-world name="World"> </hello-world>
</div>
</div>
<!-- ng-template simulates a separate file -->
<script type="text/ng-template" id="my_component.html">
<input class="form-control" ng-model='$ctrl.name'><br><span>Hello {{$ctrl.name}}, I'm {{$ctrl.myName}}!</span>
</script>
<!-- This script can be also written as:
<script src="/app.js"></script>
if the file `app.js` is located in root directory of the server,
which should contain the AngularJS code below
-->
<script>
var app = angular.module('myApp', ['ui.bootstrap']); // injected dependancies
app.component("helloWorld", {
templateUrl: "my_component.html",
/* component template */
bindings: {
name: '#'
},
controller: function() {
this.myName = 'Karolyn'; // use of `this` requires `$ctrl` in the template HTML
}
});
</script>
</body>
</html>
For some reason when I try to run Angular 1.5 I get a 404 error. Also I am using typescript with typings to compile my files. I noticed that two angular.min.js files are compiled, one that has all the code and another one that is an empty file. The 404 error directs to the empty file.
This is my HTML
<!doctype html>
<html>
<head>
</head>
<body ng-app="app">
<header></header>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="Scripts/app.js"></script>
</html>
JS
/// <reference path="../typings/index.d.ts" />
var app = angular.module("app", []);
app.component('header', {
controller: function () {
this.header = "Hello World";
},
template: "\n\t\t<h3>{{$ctrl.header}}</h3>\n\t"
});
//# sourceMappingURL=app.js.map
EDIT: I tried using a local file of angular but that made no difference.
I have the most simple little Ionic App that works as expected when run in the browser using ionic serve.
However, when the app is run in Ionic View (view.ionic.io), the routing appears to be failing (the index.html is loaded, but nothing within <div ui-view=""></div> is loaded. This is done using ionic upload.
My simple index.html looks like:
<body ng-app="app">
my app!
<div ui-view=""></div>
</body>
My app.js contains:
angular
.module("app", [
"ionic",
"ngCordova",
"ui.router"
])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider.state("splash", {
url: "/splash",
templateUrl: "components/splash/splash.html",
controller: "SplashController"
}).state("login", {
url: "/login",
templateUrl: "components/login/login.html",
controller: "LoginController"
});
$urlRouterProvider.otherwise("/splash");
});
I have a SplashController that has:
var SplashController = (function () {
function SplashController($scope) {
this.test = null;
this.scope = null;
$scope.vm = this;
this.scope = $scope;
this.test = "Hello world!";
}
SplashController.$inject = ["$scope"];
return SplashController;
})();
App.SplashController = SplashController;
angular.module("app").controller("SplashController", App.SplashController);
And my really boring splash.html is:
<div class="padding">
<h4 class="title dark">splash.html</h4>
<h4 class="title dark">{{ vm.test }}</h4>
</div>
In my browser (ionic serve) I see:
And on my device (ionic upload / Ionic View app) I just see my app!
What am I doing wrong? Is this an issue with the Ionic View app? Has anyone else run into this?
A few other things to note:
The JavaScript is compiled from TypeScript.
I had attempted <ion-nav-view></ion-nav-view> / excluding ui.router and the results were the same (works in the browser, but not on the device). I actually dislike the Ionic view animations and prefer to use the standard ui-router, if I can.
Well this turned out to be the strangest of issues. After further debugging, I realized that not only was the router not working, but Angular was not working at all ({{ 1 + 1 }}) displayed literally.
For some reason, the native app did not like my generated JavaScript in a .tsout directory. I removed it and placed the same exact file in the same directory as my index.html. I'm sure something else was going on behind the scenes, but re-structuring my project files seemed to solve the problem.
The setup with the error:
Project structure:
/www
/.tsout
app.js // both .tsout and app.js are created through my gulp-typescript task
/components
/css
/img
/lib
/typings
index.html
HTML head:
<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="css/ionic.app.min.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/ionic/js/ng-cordova.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<script src=".tsout/app.js"></script>
</head>
The solution:
My project structure after I found success both in the browser and on the device:
/www
/components
/css
/img
/lib
/typings
index.html
app.js // just app.js is created through my gulp-typescript task
The script tag in the head then looks like:
<script src="app.js"></script>
Hope the outcome of this wonkiness can be helpful to someone else!
I'm very new, (a total newb) to both AngularJS and BDD testing with Jasmine. My goal for this weekend is to become a little more competent with both.
I'm currently following the tutorial that's available on the angularJS site and I'm working on the files locally. In Chapter 2 it briefly touches on creating Angular tests with Jasmine.
However, I've done exactly as the tutorial states and Jasmine is failing. The test is simply to ensure that exactly 3 phones are rendered in the HTML. (which there are).
Here's the test:
describe('PhoneListCtrl', function() {
it('should create "phones" model with 3 phones', function() {
var scope = {},
ctrl = new PhoneListCtrl(scope);
expect(scope.phones.length).toBe(3);
});
});
The error that I'm getting on my tests.html page is:
ReferenceError: PhoneListCtrl is not defined
Here's tests.html:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v2.0.0</title>
<link rel="shortcut icon" type="image/png" href="jasmine/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="jasmine/jasmine.css">
<script type="text/javascript" src="jasmine/jasmine.js"></script>
<script type="text/javascript" src="jasmine/jasmine-html.js"></script>
<script type="text/javascript" src="jasmine/boot.js"></script>
<!-- include source files here... -->
<script src="js/controllers.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec/spec.js"></script>
</head>
<body>
</body>
</html>
I know there's nothing wrong with js/controllers.js because 3 phones are being rendered (by Angular) in my index.html page so I've definitely gone wrong somewhere with setting up Jasmine but not entirely sure where...
Update:
PhoneListCtrl is defined as follows:
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function ($scope) { .. });
I have also tried the following:
describe('PhoneListCtrl', function(){
beforeEach(module('phonecatApp'));
it('should create "phones" model with 3 phones', inject(function($controller) {
var scope = {},
ctrl = $controller('PhoneListCtrl', {$scope:scope});
expect(scope.phones.length).toBe(3);
}));
});
but with the above I get 'module' is not defined...
The tutorial project Angular-phonecat is based on angular-seed which uses karma test runner to run jasmine tests.
All the JS files should be included on karma config file test/karma.conf.js. See the example from angular-phonecat sources. The line that will include the PhoneListCtrl is:
'app/js/**/*.js'
Tests can be run using npm test which equals to karma start test/karma.conf.js (the command is configured on package.json file)
If you have cloned the angular-phonecat project like instructed on the tutorial main page, you should already have working karma config file.
Very new to AngularJS, I am guessing the term for what I am trying to do is lazy load. I have looked at several different blogs and I have not found a complete working solution that is purely using AngularJS.
I understand that if I put the <script src="js/process1.js"></script> in index.html, all works fine, I am trying to cut down on the amount of js that is pulled down on the initial load.
With the script tag sitting in the partial, it is never loaded so the P1Ctrl is never created. So currently, if a user go into the application and never goes to process55, the user still has the code there for process55 even though it was never used.
Is there a way to load the file and inject the objects created in the process1.js into the app defined in main, at the time process1 route is executed?
index.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Large Angular App</title>
<link rel="stylesheet" href="lib/foundation/css/foundation.min.css" />
</head>
<body ng-app="largeApp" ng-controller="LargeAppController">
<div>
Home | Process1
</div>
<br/>
<br/>
<br/>
<ng-view>Test</ng-view>
<script type="text/javascript" src="lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angular/angular-route.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
js/main.js:
var app = angular.module("largeApp", ['ngRoute']);
var appCtrl = app.controller("LargeAppController", function(){});
app.config(function ($routeProvider, $controllerProvider) {
// save references to the providers
app.registerCtrl = $controllerProvider.register,
$routeProvider.when('/', {templateUrl: 'partials/home.html'});
//Thinking I need to set up a resolve to fire off a script loader to load js.
$routeProvider.when('/process1', {templateUrl: 'partials/process1/process1.html'});
$routeProvider.otherwise({redirectTo: '/'});
});
partials/home.html:
<div>
Home Page
</div>
partials/process1.html:
<script type="text/javascript" src="js/process1/Process1Controller.js"></script>
Process 1 {{process1data}}
js/process1.js:
console.log("I made it here");
app.registerCtrl('Process1Controller',function($scope){
$scope.process1data = "Hello!";
}
]);
To implement lazy loading of controllers in simple way, you have to do the following:
Save $controllerProvider.register (which is the only method to add a controller into already bootstrapped AngularJS app) to variable in your app (main.js):
var app = angular.module('app',["ngRoute"]);
app.config(['$routeProvider', '$controllerProvider',
function($routeProvider, $controllerProvider) {
// remember mentioned function for later use
app.registerCtrl = $controllerProvider.register;
//your routes
$routeProvider.when('/', {templateUrl: 'partials/home.html'});
$routeProvider.when('/process1', {templateUrl: 'partials/process1.html'});
$routeProvider.otherwise({redirectTo: '/'});
}
]);
process1.html:
<script src="js/process1.js"></script>
<div ng-controller="P1Ctrl">
{{content}}
</div>
And now, in process1.js you use our registerCtrl:
app.registerCtrl('P1Ctrl', function($scope)
{
$scope.content = '...';
});
index.html probably remains the same. Check if your process1.js is being loaded (simply using console.log() right in the body of process1.js, not in P1Ctrl controller). If it isn't, include jQuery before Angular:
<script src="lib/jquery/jquery.js"></script>
<script src="lib/angular/angular.js"></script>
IMPORTANT: This method doesn't work with angular 1.2.0-rc.2 and 1.2.0-rc.3, because this little trick with jQuery doesn't work.
For more complex (and prettier) solution, with .js files as dependencies in route definitions, check that article: http://ify.io/lazy-loading-in-angularjs/ - it also works with rc.2 and rc.3. Here is plunk implementing described method: http://plnkr.co/edit/ukWikO5TVDtQ1l9WlrGD