I tried so hard to get this work but all my tries failed. I'm trying to learn Angular routing, I started very simple: created 4 files in the same folder: index.html, page1.html, page2.html and page3.html.
this is the index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>routing</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<script src="D:\Developer Library\MyAngular\angular.min.js"></script>
<script src="D:\Developer Library\MyAngular\Scripts\angular-route.js"></script>
<body ng-app="myApp">
one
two
three
<div ng-view></div>
<script>
var app = angular.module('myApp', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/page1', { templateUrl: 'D:\Developer Library\dom\AngularRouting\page1.html' }).
when('/page2', { template: '<h1>page2.html</h1>' })//the template is working fine unlike templateUrl
.when('/page3', { template: '<h1>page3.html</h1>' });
//page1.html, page2.html, page3.html are just files holding headers with some text.-->
})
</script>
</body>
</html>
I got these errors in the console window:
XMLHttpRequest cannot load
file:///D:/Developer%20LibrarydomAngularRoutingpage1.html. Cross
origin requests are only supported for protocol schemes: http, data,
chrome, chrome-extension, https, chrome-extension-resource.
and:
Error: [$compile:tpload]
http://errors.angularjs.org/1.5.8/$compile/tpload?p0=D%3ADeveloper%20LibrarydomAngularRoutingpage1.html&p1=-1&p2=
at angular.min.js:6
at angular.min.js:156
at angular.min.js:131
at m.$eval (angular.min.js:145)
at m.$digest (angular.min.js:142)
at m.$apply (angular.min.js:146)
at HTMLBodyElement. (angular.min.js:115)
at Sf (angular.min.js:37)
at HTMLBodyElement.d (angular.min.js:37)
I made every possible change to get it work: I changed the href value of the anchor elements to /#/page1, #/page1, /page, page , I also changed the templateUrl value to similar values (my last try was the full path of the file!)
I'm actually confused between the href value and the first parameter of when method and the templateUrl, so I have some questions that I think will help me understand how routing work in angular:
What each of them refers to: are the href and the first argument of when method the same?
Can I assign the href attribute any value, and refer to it in the when argument?
Is templareUrl value related to the location of the current file(index.html),
What does the hash symbol # mean and why it's important?
Angular is loading templates via AJAX, and AJAX can not access local file system.
You must run you app on a server (you can use local server) for templateUrl to work.
Related
I am trying to use HTTPD's mod_rewrite and AngularJS's routeProvider to allow users to access a webpage with a clean URL that will change its content based on some parameters in the URL.
For example, let's say there are profile pages for JohnSmith and JaneDoe. I want them to be able to access their pages via URL, like so:
http://my.example.com/JohnSmith
I want the AngularJS code to be able to grab the name "JohnSmith" from the URL, and use that for the REST call thusly:
$http.get('http://my.example.com/profile/name/' + $routeParams.profile)
So far, I have managed to get AngularJS to grab the correct profile IF the URL is formatted like one of the following:
http://my.example.com/#/JohnSmith
http://my.example.com/index.html#/JohnSmith
Here is the relevant code thus far:
index.html:
<html ng-app="profile">
<head>
<title>Profile</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<link rel='stylesheet' href='style/style-main.css' type='text/css' />
<script src="js/app.js"></script>
</head>
<body>
<ng-view></ng-view>
</body>
</html>
app.js:
(function() {
var app = angular.module('profile', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider.when("/:profile",
{
templateUrl: "profile.html",
controller:"ProfileController",
controllerAs: "profile"
});
});
app.controller("ProfileController", [ '$http', '$routeParams', function($http, $routeParams) {
var SELF = this;
SELF.profile = $routeParams.profile;
console.log(SELF.profile);
}) ();
Using a clean URL like this:
http://my.example.com/JohnSmith
...will return a 404.
So I'm trying to use Apache's mod_rewrite to change the URL into a form that AngularJS can understand and extract the 'JohnSmith' parameter from.
I've got the following RewriteRule in place on my Apache node:
RewriteRule "(^[^\/#\.]+$)" "#/$1"
I've checked it out, and I know that this RewriteRule should trigger on any URL that doesn't contain any extra slashes, pound signs, or periods. Therefore, it should rewrite a URL like this:
http://my.example.com/JohnSmith
to this:
http://my.example.com/#/JohnSmith
That's a form that I know AngularJS can serve content for correctly, so after Apache rewrites the URL into that form, it should work, right?
Well, with that RewriteRule in place, trying to access the clean URL no longer results in a 404. In fact, if I right-click and select 'View Source', I can see that my browser has definitely attempted to load the HTML page. It looks like the routeProvider is no longer picking up the parameter from the URL, however.
How can I resolve this issue so the HTTPD RewriteRule and AngularJS routeProvider work together to provide the correct content using the clean URL?
This question already has answers here:
Removing the fragment identifier from AngularJS urls (# symbol)
(14 answers)
Closed 7 years ago.
Is it possible to not to give # symbol from url to display record by giving id from url directly?
I am developing a website in which I have only one view page as Login.html.
I need to access it by giving id of user from url as abc.in/1 here 1 is id of user. I set Login.html as a default page and when I try to access it by giving abc.in/1 ,i.e. id in url it can not display the record. but when I give abc.in#/1 it displays the record properly. I dont want to access it by giving # in url.
My code is as follow-
<html ng-app="myApp" style="height: 500px; overflow: auto;">
<head>
<meta charset="utf-8">
<base href="/">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title style="color: white;">c60</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script src="../app/js/controllers/LoginController.js"></script>
</head>
<body>
---record details
</body>
</html>
and in app.js-
angular.module('myApp', [
'ngRoute', 'ngResource', 'ngCookies',
'myApp.filters',
'myApp.services',
'myApp.directives',
'myApp.controllers',
'ui.bootstrap', 'ngAnimate', 'ngDragDrop' //'ngSanitize',
]).
config(['$routeProvider','$locationProvider', function ($routeProvider,$locationProvider) {
$routeProvider.when('/:id',
{
templateUrl: '/Login.html',
controller: 'LoginController'
});
$routeProvider.otherwise({ redirectTo: '' });
//check browser support
if (window.history && window.history.pushState) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
}
}])
How to do that? I just dont want to give # in url to display a record of perticular id provided in url.I need a clean url.How to do that?
I tried to remove the # from my ulrs using the tip from the following question Removing the # symbol from angular.js urls .Now, the issue is that my url is not working if I try a direct access to them. from the given example in the related question if put the url below directly in the browser http://localhost/phones ; in my case it is abc.in/1
I'll get a 404 error. Any idea how to solve this?
It is possible to suppress the # in the url of an angular application. To do so, you need to configure the $locationProvider which you already have injected in your app config. Add the following after the $routeProvider configuration
$locationProvider.html5Mode(true);
Finally add the following to the head section of your html file
<base href="/">
A couple of things seem to be wrong here. First even when you are having only one view in your app, it is nice to have something like an index.html which will host your ng-view directive. then when you navigate to the one view of your app, that view will be loaded where you have the ng-view directive. Secondly, from your app.js, you have something as shown below
$routeProvider.when('/:id',
{
templateUrl: '/Login.html',
controller: 'LoginController'
});
$routeProvider.otherwise({ redirectTo: '' });
So this clearly says that when you enter '/' or '/1' for example in the address bar of your browser your application will fetch login.html as stated in the templateUrl. However, in your test you are entering abc.in/1 (which I do not know where it comes from)in the url address bar of your browser. when this url is checked in the route provider's routes, no match will be found. Hence you you get a 404 error. To make the matter worse your $routeProvider.otherwise is redirecting to empty string. The right thing to do is state the various routes with their respective templateUrl for your application and set otherwsise to redirect to the root of your application which in your case is still login.html or index.html if you add that now as you have only one view. Hope this helps.
I am currently at /addDoc, and I want current route I am at. Here is my controller:
app.controller('DocRegistrationController',[ '$http', '$scope', '$upload', '$location', function($http, $scope, $upload, $location){
$scope.validation=function(){
alert($location.path());
}
}
However it returns empty. I dont want to hardcode all the routes. What am I doing wrong?
$location service respond for parsing url in browser address bar and make the URL available to your APP.
Because you're using regular URL path and search segments, you have to set $locationProvider html5Mode to true.
$locationProvider will use hashbang as default mode.
If you don't set html5Mode to true, you will get empty string when you try to fetch url path.
Then use $location service to fetch the url path after set html5Mode.
And write your own rule to process the path.
Assume that your Full URL looks like: http://example.com/person/show/321
Main.js
angular.module("MyAPP",[],function($locationProvider){
$locationProvider.html5Mode(true);
});
function MainController($location){
var pId = $location.path().split("/")[3]||"Unknown"; //path will be /person/show/321/, and array looks like: ["","person","show","321",""]
console.log(pId);
}
index.html
<!DOCTYPE html>
<html lang="en" ng-app="MyAPP">
<head>
<meta charset="utf-8">
<title>Angular test</title>
</head>
<body ng-controller="MainController">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
Hope this is helpful for you.
Use $location.absUrl()....Full URL Looks like : http://localhost:6292/Example/URLName
Try also this, which is native code in JS. It worked for me. But if you need to parse long url with many nested pages, you have to modify the code a bit.
var path = "/" + window.location.pathname.split('/')[1];
console.log(path
);
I am building a web Single Page Application using AngularJS. I need that clicking on link change URI in client browser without http request.
http://example.com/ ---> it shows my single page application and clicking on a specific link I need the URL is http://example.com/about but without send http request and show hidden div.
I don't know what you precisely want to do but if you only want do one http request you can perhaps use angular ui router with something like
$stateProvider
.state('main', {
url: "/",
templateUrl: "main.html"
})
.state('about', {
url: "/about",
templateUrl: "main.html",
controller: function($scope) {
$scope.showDiv = "true";
}
})
That way you can switch state and because everything you need is already loaded, nothing gets loaded anymore. Or perhaps you can also use parameters.
But why is it so bad to have one additional request? That would be something interesting to know! :)
EDIT: The easy approach with $location
(https://docs.angularjs.org/guide/$location)
index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
<base href="/">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="html5-mode">
<div ng-controller="LocationController">
<button ng-click="changeUrl()">Change url</button>
</div>
</body>
</html>
app.js:
angular.module('html5-mode', [])
.controller("LocationController", function ($scope, $location) {
$scope.$location = {};
$scope.changeUrl = function () {
// https://docs.angularjs.org/guide/$location
console.log("The current path: " + $location.path());
console.log("Changing url...");
$location.path('/newValue')
};
})
.config(function ($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
Be sure to set the basePath correct.
Take a look at html2js. This is a grunt task to convert your html templates into a pre-cached js file.
Ideally you would run this as part of your build process. As well you can run a watch task to compile your HTML templates into the pre-cache whenever you save a template -- this is nice for development.
If you are already using gulp, there is a package for you. There are many alternatives to html2js that do essentially the same thing. So if it doesn't suit your needs, try another.
So with this in place, when you navigate to another page -- the HTML template will just be pulled out of angular's cache, and not grabbed from the server.
I've an app that retrieve server data using ajax. I've tested in localhost, the loader work fine, but when I install my extension and click on the browser action popup, the loader won't show. The little popup delayed for 2 second and shows the result.
popup.html
<div class="cssLoader" ng-show="loader">Fetching...</div>
js
app.controller('MainControl', function($scope, $http){
$scope.loader = true;
$http({
url: "http://www.corsproxy.com/mydomain.net/items.php",
method: "GET",
}).success(function(data) {
$scope.data = data;
$scope.loader = false;
});
});
Without seeing more of your code it is difficult to know for sure. Nonetheless, my suspicion (based upon the fact that your code works outside of the Chrome extension environment but not inside that environment) is that since you're operating in a Chrome Extension environment, you'll need to include the ng-csp directive (see Chrome documentation or Angular documentation).
I developed an Angular app inside a chrome extension and I needed to use ng-csp in order for Angular to load and fully function properly.
Essentially, Chrome extensions (and even more apps) place a number of restrictive security permissions on the browser environment and ng-csp tells Angular to operate in a way that is more consistent with a strict CSP.
I have included an example below that shows loading the entire Angular application properly:
<!DOCTYPE html>
<html ng-app="myApp" ng-csp>
<head>
<meta charset="utf-8">
<title>My Extension</title>
<link href="css/index.css" rel="stylesheet">
<!-- Include in the next line your Angular library code -->
<script type="text/javascript" src="js/angular-lib.js"></script>
<!-- Include in the next line your custom Angular code such as the $http to load the loader -->
<script type="text/javascript" src="js/myapp.js"></script>
</head>
<body>
<!-- Place your HTML code for the 'Fetching' anywhere here in the body -->
</body>
</html>
According to the docs, CSP "is necessary when developing things like Google Chrome Extensions" (more info can be found on the linked page).
Furthermore, besides defining ng-csp on your root element, there is on more crucial point (which affects ngShow/ngHide):
CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically includes some CSS rules (e.g. ngCloak). To make those directives work in CSP mode, include the angular-csp.css manually.
I found this to be necessary only if the angular.js script is defined inside the app's context.
In any case, here is the source code of minimal demo extension that seems to work fine for me:
Structure:
extension-root-dir/
|_____manifest.json
|_____popup.html
|_____popup.js
|_____angular.js
|_____angular-csp.css
manifest.json:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"browser_action": {
"default_title": "Test Extension",
//"default_icon": {
// "19": "img/icon19.png",
// "38": "img/icon38.png"
//},
"default_popup": "popup.html"
}
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<title>Test Extension</title>
<link rel="stylesheet" href="angular-csp.css" />
</head>
<body ng-csp ng-app="myApp" ng-controller="mainCtrl">
<div ng-show="loader">Fetching...</div>
<div ng-hide="loader">{{status}}</div>
<script src="angular.js"></script>
<script src="popup.js"></script>
</body>
</html>
popup.js:
var app = angular.module('myApp', []);
app.controller('mainCtrl', function ($http, $scope) {
$scope.loader = true;
$http({
url: "http://www.corsproxy.com/mydomain.net/items.php",
method: "GET"
}).finally(function () {
$scope.loader = false;
}).then(function (response) {
$scope.data = response.data;
$scope.status = 'Success !';
}, function (response) {
$scope.status = 'ERROR !';
});
});
(BTW, I am using AngularJS v1.2.16.)