How do I parse URL params after a hash with Angularjs? - javascript

I'm trying to parse for the access_token from Foursquare where the URL is like this:
https://mywebsite.com/4sqredirect/#access_token=1234567890XXXXX
I've tried $routeParams and $location and get nothing returned. Only after I tried $route, I did get an object back with the following attribute in it:
current: {
params: { }
pathParams: { }
loadedTemplateUrl: partials/4sqredirect
locals: { }
scope: {
this: {
$ref: $["current"]["scope"]
}
route: {
$ref: $
}
location: { }
token: null
}
}
Does this mean there's no way to get it using native AngularJS functions cause of the hash?
UPDATE:
my controller looks like as follows:
angular.module('myApp')
.controller('4sqredirectCtrl', function ($scope, $route, $location, $routeParams) {
$scope.route = $route;
$scope.location = $location;
$scope.token = $routeParams.access_token;
});
my main js looks like as follows:
angular.module('myApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute'
])
.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: 'partials/main',
controller: 'MainCtrl'
})
.when('/4sqredirect/', {
templateUrl: 'partials/4sqredirect',
controller: '4sqredirectCtrl'
})
.otherwise({
redirectTo: '/'
});
});

From angular location service $location.hash() method return #after-hash
so if your url is look like
https://mywebsite.com/4sqredirect/#access_token=1234567890XXXXX
then
$location.hash() return access_token=1234567890XXXXX
you need to split it split('=')[1]
see this plunker when you click 4Square then $location.url() return
/4sqredirect/#access_token=123456
$location.hash().split('=')[1]
return 123456

Use $location.search()
//e.g. url https://www.example.com/#!?name=123
var s = $location.search();
// {name: '123'}
http://docs.angularjs.org/api/ng.$location
Search:
Returns search part (as object) of current url when called without any parameter.

I'm not aware of a "native angular" way to do it, but you do have access to the hash via location.hash as a string type. it's probably not ideal, but it's workable.

There is in fact no direct support from Angular JS to do this. I wouldn't use ngRoute, because it already might expect the # at a different place. A simple solution to your problem is to use the location.hash and the substring() function:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="http://code.angularjs.org/1.2.6/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script>
angular.module('app', [])
.controller('AppCtrl', ['$scope', '$window', function($scope, $window) {
$scope.accessToken = $window.location.hash.substring(14);
}]);
</script>
</head>
<body ng-controller="AppCtrl">
<h1>Access Token</h1>
<p>{{accessToken}}</p>
</body>
</html>

Related

AngularJS: Same template is used by two different URL, I want to change some parts of view when on other URL

For example I have this input button:
<input type="button" class="blue-button pull-right" value="{{gb.gebruikerToevoegenText}} toevoegen" ng-click="gebruikers.addGebruiker()"/>
In the controller I am trying to achieve this through this logic:
vm.gebruikerToevoegenText = $location.path() == '/gebruikers' ? "Super User" : "Gebruiker";
But this guides me to same url for both views i.e. /gebruikers
I want its value to be different when the URL is /gebruikers/:id?/:naam?', below is the route definition:
$routeProvider.when('/gebruikers/:id?/:naam?', {
templateUrl: 'gebruikers.html',
controller: 'gebruikersController as gebruikers',
resolve: {
authentication: ['fwgAuthService', function (fwgAuthService) {
return fwgAuthService.login();
}]
}
});
$routeProvider.when('/gebruiker/:licentieHouderId/:id?', {
templateUrl: 'gebruiker.html',
controller: 'gebruikerController as vm',
resolve: {
authentication: ['fwgAuthService', function (fwgAuthService) {
return fwgAuthService.login();
}]
}
});
I want to change user rights as well on this URL , but only if I know how to manipulate the view based on URL, I do not want to change the template, other wise it is going to be lots of copy and paste.
You'll have to change the template anyways. Please don't pollute the rootScope for this; you can use ng-if or ng-show/hide (as already suggested). Just add an isAuthorized() function to your controller and set a flag if the url matches a certain pattern. Moreover I would alter the controllerAs name to the same name for both path in order to make templating easier.
I checked the url by using the following function in the controller thanks for helping out:
vm.gebruikerToevoegenText = $routeParams.id ? "Super User" : "Gebruiker";
Index.html
<!doctype html>
<html ng-app="routerApp">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script>
var routerApp = angular.module('routerApp', ['ui.router', 'ngRoute']);
routerApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/gebruikers/:id?/:naam?', {
templateUrl: 'gebruiker.html',
controller: 'gebruikersController'
}).
when('/gebruiker/:licentieHouderId/:id?', {
templateUrl: 'gebruiker.html',
controller: 'gebruikerController'
}).
otherwise({
redirectTo: '/gebruikers/:id?/:naam?'
});
}]);
routerApp.controller('gebruikersController', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.toevoegen = "Pratapsss";
}]);
routerApp.controller('gebruikerController', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.toevoegen = "Pratap";
}]);
</script>
</head>
<body>
<div ng-view></div>
</body>
</html>
gebruiker.html
<div>
<input type="button" class="blue-button pull-right" ng-value="toevoegen" ng-click="gebruikers.addGebruiker()"/>
</div>

AngularJS routing without webserver?

I'm trying to create a simple website using angular as front-end.
Is there a way to create partial views and routing without having a webserver?
I've been trying to do so, but I keep getting this error:
Uncaught Error: [$injector:modulerr]
Here's my code: index.html
<!DOCTYPE html>
<html lang="en" ng-app="cerrajero">
<head>
<meta charset="UTF-8">
<title>Cerrajero</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
</head>
<body ng-controller="MainCtrl">
<div ng-view></div>
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/angular-route.min.js"></script>
<script src="js/app.js"></script>
<script type="text/ng-template" id="partials/contact.html" src="partials/contact.html"></script>
<script type="text/ng-template" id="partials/services.html" src="partials/services.html"></script>
<script type="text/ng-template" id="partials/home.html" src="partials/home.html"></script>
</body>
</html>
and the app.js:
var app = angular.module('cerrajero', []);
app.config([function ($locationProvider, $routeProvider) {
$locationProvider.html5Mode(true);
$routeProvider.
when('/services', {
template: 'partials/services.html'
}).
when('/contact', {
template: 'partials/contact.html'
}).
when('/home', {
template: 'partials/home.html'
}).
otherwise({
redirectTo: '/home',
template: 'partials/home.html'
});
}]);
function MainCtrl ($scope) {
};
What am I doing wrong?
edit
I've added the ngRoute but I still get the same error when I open the index.html file in the browser.
var app = angular.module('cerrajero', ['ngRoute']);
app.config([function ($locationProvider, $routeProvider) {
$locationProvider.html5Mode(true);
$routeProvider.
when('/services', {
template: 'partials/services.html'
}).
when('/contact', {
template: 'partials/contact.html'
}).
when('/home', {
template: 'partials/home.html'
}).
otherwise({
redirectTo: '/home',
template: 'partials/home.html'
});
}]);
function MainCtrl ($scope) {
};
edit 2
Here's the files on github:
https://github.com/jsantana90/cerrajero
and here's the website when it loads:
http://jsantana90.github.io/cerrajero/
edit 3
I've manage to get rid of the error by having the following code:
var app = angular.module('cerrajero', ['ngRoute']);
app.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
$locationProvider.html5Mode(false);
$routeProvider.
when('/services', {
template: 'partials/services.html'
}).
when('/contact', {
template: 'partials/contact.html'
}).
when('/home', {
template: 'partials/home.html'
}).
otherwise({
redirectTo: '/home',
template: 'partials/home.html'
});
}]);
app.controller('MainCtrl', function ($scope) {
});
I added this app.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
But now my page is blank. It doesn't redirects or anything.
Have I placed everything how it's suppose to go?
edit 4
I forgot to change ui-view to ng-view. Now it works but it's showing in the view: partials/home.html instead of the actual view.
edit 5
Ok so, after having this final code:
var app = angular.module('cerrajero', ['ngRoute']);
app.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
$routeProvider.
when('/services', {
templateUrl: './partials/services.html'
}).
when('/contact', {
templateUrl: './partials/contact.html'
}).
when('/home', {
templateUrl: './partials/home.html'
}).
otherwise({
redirectTo: '/home'
});
}]);
app.controller('MainCtrl', function ($scope) {
});
I get this error:
XMLHttpRequest cannot load file:///partials/home.html. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
Now I'm guessing this is because I don't have a webserver running. How do I get it to work without a webserver?
solution
When I uploaded the files to github it seems to work there, but not locally.
Looks like you are using ngRoute and forgot to include it!
First load angular-route.js after loading angular.js. The inject ngRoute as a module:
var app = angular.module('cerrajero', ['ngRoute']);
Try removing the array syntax brackets from inside your config function. I believe there are two different ways of invoking these functions, either with a standalone function or with an array for any minification processes.
You should either one of the following:
app.config(function ($locationProvider, $routeProvider) {
// your code here
});
Or define the variable names with the array syntax for use in minifiers
app.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
// your code here
}]);
When you pass in an array to the config function, I believe Angular is expecting the first parameters to be a string value.
You should use ui-router instead of ng-route. It will allow you to nest views. Most current Angular projects use ui-router. ui-router scotch.io
Also, for your controller try app.controller('MainCtrl', function($scope){...});
Replace
var app = angular.module('cerrajero', []);
with
var app = angular.module('cerrajero', ['ngRoute']);

AngularJS error ng areq not a function

I'm trying to make my meta controller to dynamically change the meta tags, but in console i get error ng areq not a function. I searched through StackOverflow for similar problems but none of the solution is for my problem. I have these tags in my HTML:
<html ng-app="WebApp" >
<head ng-controller="MetaDataCtrl">
<meta name="description" content="{{ meta.tags.description }}">
</head>
<body >
<div ng-include='"templates/header.html"'></div>
<div ng-view></div>
</body>
</html>
Main.js
var app = angular.module('WebApp', [
'ngRoute'
]);
/**
* Configure the Routes
*/
app.config(['$routeProvider', '$locationProvider', function($routes, $location) {
$location.html5Mode(true).hashPrefix('!');
$routes
// Home
.when("/", {templateUrl: "partials/home.html",
controller: "PageCtrl",
metadata: {
title: 'This is my title',
description: 'This is Desc.' }
})
}]);
app.controller('PageCtrl', function (/* $scope, $location, $http */) {
});
.controller('MetadataCtrl', function ($scope, metadataService) {
$scope.meta = metadataService;
});
There is no such service metadataService and you don't defined it yourself. However, looks like you just need to accecc current route metadata object. In this case it's quite easy to do as it's part of the $route service. you should also set up a listener to update global meta object when route changes:
app.run(['$rootScope', function($rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current) {
$rootScope.meta = current.metadata;
});
}]);
Demo: http://plnkr.co/edit/nQfqNWvoYQQElv909uZF?p=preview

Split controllers into separate files

I had an angular setup that looked like this:
var dashboard = angular.module('Dashboard', ["ngRoute", "highcharts-ng"]);
dashboard.config(function($routeProvider, $locationProvider){
$routeProvider.when('/route1', {
templateUrl: 'route1.html',
controller: 'DefaultCtrl'
});
})
.controller('DefaultCtrl', function($scope, $rootScope, $http, settings){
function($scope, $rootScope, $http, settings){
$http.get("http://admin.gmserver.net/games/all?userId=" + settings.userId).success(function(data){
$scope.games = data;
$rootScope.gameId = "";
$rootScope.gameName = "";
$rootScope.apiName = "";
$rootScope.$broadcast("loaded");
});
}
})
And this worked. I then tried to split them up into multiple files (one for each controller), and now it looks like this:
module file:
angular.module('Dashboard', ["ngRoute", "highcharts-ng"]);
angular.module('Dashboard').config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider){
$routeProvider.when('/route1', {
templateUrl: 'route1.html',
controller: 'DefaultCtrl'
});
}
])
controller file:
angular.module('Dashboard').controller("DefaultCtrl", ['$scope', '$rootScope', '$http', 'settings',
function($scope, $rootScope, $http, settings){
$http.get("http://admin.gmserver.net/games/all?userId=" + settings.userId).success(function(data){
$scope.games = data;
$rootScope.gameId = "";
$rootScope.gameName = "";
$rootScope.apiName = "";
$rootScope.$broadcast("loaded");
});
}
]);
Now when I load the page I get this:
I am loading the files like this:
<script src="http://code.highcharts.com/adapters/standalone-framework.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="/media/js/highcharts-ng.min.js"></script>
<!-- Begin app code -->
<script src="/admin/Dashboard.js"></script>
<!-- Built with smarty -->
<script>
angular.module('Dashboard').value("settings", {
userId: "{$userId}",
secret: "{$secret}"
});
</script>
<script src="/admin/components/default/DefaultController.js"></script>
<script src="/admin/components/game/GameController.js"></script>
<script src="/admin/components/leaderboard/LeaderboardController.js"></script>
<script src="/admin/components/newsFeed/NewsFeedController.js"></script>
I do notice that commenting out one of the following stops the Aw, Snap error.
DefaultController.js file
Inline JavaScript
highcharts-ng.min.js file
Edit:
I changed the name of the module to my site's name and made the Dashboard a dependency like this:
angular.module('GMServer', ["ngRoute", "highcharts-ng", "Dashboard"]);
angular.module('Dashboard')
This fixes the "Aw, Snap" issue, but now I get this error: https://docs.angularjs.org/error/$injector/nomod?p0=Dashboard
I'm not entirely sure what happens when you call the same angular.module several times but I would avoid it.
You want to save the module globally so then you can reference it in different files instead of calling angular.module('Dashboard') each time:
window.Dashboard = angular.module('Dashboard', ["ngRoute", "highcharts-ng"]);
window.Dashboard.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider){
$routeProvider.when('/route1', {
templateUrl: 'route1.html',
controller: 'DefaultCtrl'
});
}
])
and
window.Dashboard.controller("DefaultCtrl", ['$scope', '$rootScope', '$http', 'settings',
function($scope, $rootScope, $http, settings){
$http.get("http://admin.gmserver.net/games/all?userId=" + settings.userId).success(function(data){
$scope.games = data;
$rootScope.gameId = "";
$rootScope.gameName = "";
$rootScope.apiName = "";
$rootScope.$broadcast("loaded");
});
}
]);
You'll just need to make sure your <script> tags are included in the correct order.
Avoid polluting the window object though, you may wanna namespace everything under window.App or use someting like requireJS or Browserify.
Edit
It's perfectly safe to retrieve a module like the OP is doing as pointed out #Sunil and documented here

What's the best way to determine a route's template based on $cookies value in AngularJS?

I'd like the root URL, /, of my AngularJS app to display a template based on cookie value. For example, when a login cookie is present display dashboard. When login cookie is absent, display a login screen.
I tried to inject $cookies to app.config to determine the template property of $route based on it, but that didn't work.
var myApp = angular.module('myApp', ['ngRoute', 'ngCookies']);
myApp.config([
'$routeProvider',
'$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: function() {
// read cookies here?
return '../../connect.html';
},
controller: "getAuthUrl"
});
$locationProvider.
html5Mode(true).
hashPrefix('!');
}
]);
Answering my own question...
After further investigation, I found out that $routeProvider is not what I should be using. $routeProvider is for serving templates based on URL routes. What this problem needed is the ui-router module, which is an official AngularJS module.
Instead of URLs, ui-router lets you specify page content based on "state". In my situation, I have a "loggedin" state and a "dashboard" state. Here's how I have implemented the solution:
var myApp = angular.module('myApp', ['ngCookies', 'ui.router']);
myApp.config([
'$stateProvider',
'$locationProvider',
function ($stateProvider, $locationProvider) {
$stateProvider.
state('login', {
template: '<h1>Login now.</h1>'
}).state('dashboard', {
template: '<h1>You are logged in. Welcome.</h1>'
});
$locationProvider.
html5Mode(true).
hashPrefix('!');
}
]);
myApp.controller('mainCtrl', [
'$scope',
'$state',
'$cookies',
function($scope, $state, $cookies) {
// You can read cookies here
if (true) {
console.log($cookies);
$state.go('dashboard');
}
else {
$state.go('login');
}
}
]);
And then the HTML is
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script src='js/lib/angular.js'></script>
<script src='js/lib/angular-ui-router.js'></script>
<script src='js/lib/angular-cookies.js'></script>
<script src="js/app.js"></script>
</head>
<body ng-controller='mainCtrl'>
<div class="container" ui-view></div>
</body>
</html>
You can read all about ui-router in its wiki
Note: You have to use ui-router v0.0.2 at least. v0.0.1 won't work.

Categories

Resources