Significance of ":" in url in angularjs - javascript

I am learning angular js , and I found this in some tutorial while explaining routing.
module.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/users/', {templateUrl: 'template.tpl.html', controller: myCtrl}).
when('/users/:userId', {templateUrl: 'template.tpl.html', controller: myCtrl})
}]);
What is this :userId in the link ? what i know is suppose we have a folder template in that if we have anotherfile user we will put the link as "template/user" , I also know this userID will be used in routerParams as a parameter for route's controller but what exactly is the meaning of : in the link above ?

This represent a parameter
In this case the parameter is userID thus those urls
domain.com/users/0
domain.com/users/1
domain.com/users/2
will call the same route with userID 0, 1 and 2

:userId repesents the dynamic part of url. The value can be anything.
It is generally used for id as you can see. Used for creating dynamic routes.
Other frameworks like nodejs, in php also uses this technique.

It is RouteParamater
let user have name and id
For example you have list of names of users in one page and when you click
a user it takes to another page which shows users detail.So to let the detail page know about the clicked user you must send some identification maybe in this case userid.
Example
{{user.name}}
And access it via routparams
//Inject routeparams
var userId = routeparams.userId //user Id is defined in your route configuration

Related

ngRouting issues in Angularjs

I have login and sign-up form. I have defined login and sign-up js code in one main controller. If user is new , I have defined link below the login , on-click of url it should get re-directed to another html page. URl is getting routed, but my js code is not responding . I tried to rectify the mistake, but i couldn't achieve it.
Please let me know what mistake, I have done. Any help/advice greatly appreciated.
AngularJS code :
var app = angular.module('logapp',['toastr','ngRoute']);
app.config(['$routeProvider',function($routeProvider){
$routeProvider
.when('/login',{
templateUrl : "login.html",
controller : "credientials"
})
.when('/signup',{
templateUrl : "signup.html",
controller : "signctrl"
})
.when('/practice',{
templateUrl : "practice.html",
controller : "practicectrl"
});
$routeProvider.otherwise({ redirectTo: '/login'});
}]);
Controller code :
1. app.controller('credientials',['$scope','$route','$rootScope','$window','$location','$http','toastr','Authentication',function($scope,$route,$rootScope,$window,$location,$http,toastr,Authentication)
2. app.controller('signctrl',function($scope){});
app.controller('head',function($scope){
$scope.hometitle = "Create your account here. It's take only a minute."
});
1. Login controller
2. Signup controller
If you don't use HTML5 mode you should specify hash-prefix.
And with Angular 1.6;
The default hash-prefix used for $location hash-bang URLs has changed
from the empty string ('') to the bang ('!').
So, you can use the URL as below by default :
<a href="#!signup">
Also check: Angular 1.6 $location

Angular JS: URL parameter appears before the `#!/` and doesn't appear in $location.search()

I'm integrating a small existing Angular JS app made by someone else into an exiting website that was not built with Angular.
All the Angular JS app files are kept in a completely separate directory and then the user can click on a link to take them to the index of that sub directory. For example:
Login.
As you can see above, I need to pass a URL parameter called returnUrl. I then need to pick up this value in the Angular JS app, using:
$location.search()
However, this actually returns an empty object. I think it's because the Angular JS is appending #!/login on the URL after the URL parameter, like so:
example.com/path/to/app?returnUrl=/original/location/#!/login
If I modify the URL in the browser, moving the returnUrl parameter to the end of the URL and refresh the page, it works and $location.search() returns {returnUrl: "/original/location/"}. However, as far as I can see I'm not able to change this in my website because the parameter is part of the link to the Angular JS app and #!/login is added afterwards automatically.
I'm new AngularJS, so please explain as clearly as you can:
What is going on here? And why is the URL parameter before the #!/login?
Why does this prevent $location.search() from returning anything? If I move the param to the end of the resulting URL, it works.
What can I do to fix this?
What is going on here? And why is the URL parameter before the #!/login?
You can think of querystring parameters before the #! as a server-side parameters, and querystring parameters after the #! as client-side parameters. This is perfectly valid:
http://example.com?serverParam=client1#!angularRoute?angularParam=someValue
The server-side parameters allow you to configure how the page is served from the server and then, once server page is served and the Angular app is loaded, use the client-side parameters to supply what that particular Angular app is expecting.
Why does this prevent $location.search() from returning anything? If I
move the param to the end of the resulting URL, it works.
Because nothing was specified for the client-side parameters until you moved the values there.
What can I do to fix this?
You could change the links to be like how you modified them to get them to work: Login. or duplicate the parameter so it's available on both the server and the client Login.
You can inject $window and get the server-side values from
$window.location.search
You can inject $location and use $location.absUrl()
Here is an example of how you can set the client-side parameters from the server-side parameters:
var app = angular.module('YOURAPPNAME', []);
app.run(['$location', function($location) {
// I'm going to fake out the url so it runs in the SnippetEditor.
var url = "example.com/path/to/app?returnUrl=/original/location/#!/login"; //$location.absUrl();
var hashbangIdx = url.indexOf('#!');
var serverStr = hashbangIdx > -1 ? url.substring(0, hashbangIdx) : url;
var qIdx = serverStr.indexOf("?");
var p = qIdx > -1 ? serverStr.substring(qIdx).split(/[&||?]/) : [];
for (var i = 0; i < p.length; i += 1) {
if (p[i].indexOf('=') > -1) {
var param = p[i].split('=');
$location.search(param[0], param[1]);
}
}
}]);
app.controller('MainCtrl', ['$scope', '$location', function($scope, $location) {
$scope.params = $location.search();
}]);
<!DOCTYPE html>
<html ng-app="YOURAPPNAME">
<head>
<meta charset="utf-8" />
<title>AngularJS</title>
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<h4>Parameters:</h4>
<p ng-repeat="(name, val) in params">
{{name}}: {{val}}
</p>
</body>
</html>
You just need to use window.location.search
> window.location.search
> "?returnUrl=/original/location/"
$location.search() gives you values only if your route has defined it.
Here are the answers to your questions:
1) AngularJS appends the # at the end of the url at which the page was loaded. So, if the url to load the page already had the query parameter of returnUrl, which seems to be the case, it will always show up to the left of the #.
2) An AngularJS application, is generally only concerned about what occurs after the # in the url. AngularJS uses this for routing and passing query parameters between states and more similar stuff. The $location.search() is meant to retrieve all the query parameters after the #.
3) Here is how you can extract the query parameter that occurs before the #
function getParamFromURL (paramName) {
var searchStr = window.location.search.substring(1);
var keyValues = searchStr.split('&');
for(var i=0; i<keyValues.length; i++) {
var split = keyValues[i].split('=');
if(split[0] === paramName) {
return decodeURIComponent(split[1]);
}
}
}
var value = getParamFromURL('returnUrl');
console.log(value);
The # you're seeing in the url is actually what's called an anchor link, or fragment. It's usually done to jump to a specific element by its id, for example navigating clicking on a <a href="#footer"> will directly scroll your page if you have an element matching this id.
Angular and other frameworks, like React, make use of this functionality to create what's called a hash routing by using the hash as the current active route. The advantages of doing so is that it will allow for a very quick setup and it will work out-of-the-box on non-HTML5 browsers.
Regarding why the query parameter is before the hash, it's only because that's actually what you specified in your link. Angular considers the url you are loading as the root of the project and adds its own # with the current router after its initialization. You could potentially have a server that serves the Angular app only while specifying this query parameter, thus the importance of keeping it in place. If the query param is place after the hash, it's considered as part of the Angular app routing, thus returned when you call $location.search().
What I would advice you to do is either explicitly specifying the # in your link, or use html5 mode. Html5 mode means that you won't get the hash form in your url, rather "normal" ones that are less ugly.
To do that, you'll have to enable html5 mode in your app,
.config(function ($locationProvider) {
$locationProvider.html5Mode(true);
}
And add the meta base in your head
<base href="/" />
The thing is that now, if you try to load a page that is not the home, you'll get into a 404 issue.
To prevent that, you'll have to serve your Angular entry for each subroute of your application. There is multiple ways, depending on what you use/ want to use on the server. Here is the Angular FAQ that showcases most of them.
You can use $location.absUrl() : It will return full URL with all segments encoded according to rules specified in RFC 3986.
var resultURl = GetURLParameter('returnUrl');
console.log(resultURl);
function GetURLParameter(param) {
// var URL = $location.absUrl();
var URL = "example.com/path/to/app?returnUrl=/original/location/#!/login";
var allVariables = URL.split('?');
for (var i = 0; i < allVariables.length; i++) {
var paramName = allVariables[i].split('=');
if (paramName[0] == param) {
return paramName[1].split("#")[0];
}
}
}
============================== OR ====================================
RouteProvider and routeParams will work in your situation.
You can pass the returnUrl as a route param in the routing and get back into the controller using $routeParams.returnUrl.
What can I do to fix this?
You can try this approach to fix this.
HTML :
Login Return Url
Routing file :
$routeProvider.when('/login/:returnUrl', {
templateUrl: 'partials/partial.html',
controller: 'MyCtrl'
});
In controller, inject $routeParams :
.controller('MyCtrl', ['$scope','$routeParams', function($scope, $routeParams) {
var url = $routeParams.returnUrl;
}]);
Note :
If you're using ngRoute, you can inject $routeParams into your controller.
If you're using angular-ui-router, you can inject $stateParams into your controller.
Check this,
function getValue(key, url) {
var regex = new RegExp("[?&]" + key + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
return results[2];
}
var value = getValue("returnUrl","example.com/path/to/app?returnUrl=/original/location/#!/login");
console.log(value);

angular routing issue with custom mod folder

This is my routing code:
.when('/:mod/:page*/', {
templateUrl: function($routeParams) {
return 'pages/'+$routeParams.mod+'/' + $routeParams.page + '.html';
}
})
if the url is
/users/add
it will load html from pages/users/add.html
Now the issue is Say for example I have a list page list.html with list data
id - name - action
1 - John - Edit
When I now click on edit I need to go to the edit.html page as well as I need to pass and get the id to that html.
How can this be achievable ?
Do I need to edit my routing ?
NOTE:
I am using ng-route for routing.
assume edit.html has a separate controller and the list.html has a separate controller.
Let me know if you need more info.
You can pass id in the edit link
...
Edit
$routeProvider
.when('/edit/:id', {
templateUrl: 'edit.html',
controller: 'EditController',
....
app.controller('EditController', function($routeParams) {
console.log($routeParams.id);
....
});

ui-router url parameter with hashtag

I'm working on the routing of my angular application, but I can't seem to find the following:
example.com/#parameter
In this url the #parameter should stay #parameter and get the param data. Now it removes the # and goes to example.com/parameter
If I go to example.com/#parameter it should do the same as it would if I go to example.com/parameter
I have the following in my app.js
url: "/:bandName"
and send this data to my controller with $stateParams
Is there any way to keep the hashtag in the url ?
-- edit
so here is some code that works on enter with /#parameter
$urlRouterProvider.when(':#bandName', '/:bandName')
.otherwise('/');
$stateProvider.state('appband', {
url: "/:bandName",
templateUrl: "main.php",
controller: 'mainController'
})
$locationProvider.html5Mode(true);
With this if I go to example.com/#randomBandName I get redirected to example.com/randomBandNameand I get randomBandName as parameter in my controller
So what I need is on enter that example.com/#randomBandName stays example.com/#randomBandName and that I still get randomBandName in my controller.
But when I remove $urlRouterProvider.when(':#bandName', '/:bandName') I just get an empty page.
There are a few things that look suspect with this:
trailing slash
Are you using HTML5 mode for your URLs? I'd suggest using this URL setup url: "/parameter" if you indeed see param as more of a resource.
You might also read this - https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-make-a-trailing-slash-optional-for-all-routes
query param
If you are intending param to be a query parameter then you need this..
url: "/?parameter"
more on that here - https://github.com/angular-ui/ui-router/wiki/URL-Routing#query-parameters

Angular JS routing: get URL to stay as user inputs

I am working on an app that lets users create polls, then link that poll to other users for them to vote.
To let users give a direct link, I need two route parameters: the ID of the user who made the poll, and the poll question.
So I want to let users go to website.com/:id/:question, and then make the corresponding API get calls using those parameters to get the information.
However, the page always redirects to website.com/ no matter what is put in.
Any ideas of where I would go to change this?
EDIT://
The $routeParams seems to be the right idea!
However, I am having trouble making it work.
I set it up like so:
angular.module('voteApp')
.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'index.html',
controller : 'MainCtrl'
})
.when ('/:id/:poll', {
templateUrl : 'index.html',
controller : 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
});
Then the client side console keeps printing 'Tried to load angular more than once'
And when I switch the index.html to 'app/main/main.jade' it just prints the contents of that file.
I am fairly sure that the path to index.html is correct, since the path to main.jade is correct and I am basing the path to index.html relatively to that
If you are using NgRoute, you ought to use the $routeParams service: https://docs.angularjs.org/api/ngRoute/service/$routeParams
If you are using ui-Router, then you can use the $stateParams service: https://github.com/angular-ui/ui-router/wiki/Quick-Reference#stateparams-1
You would also need to define a route/state to correspond to the path /:id/:question as well.

Categories