how can i change the base url on condition in angularJS - angularjs

I am caught up in a situation here.
I have a switch in my login page and i want to redirect my service for authorization accordingly.
I want to load my services dynamically after checking some conditions, when i launch my application for the first time. But in angular as we have ng-app and we need to inject all the modules in it at the start. My base url is set before the app is launched. Is it possible to change my base url on condition?
On launching the application the base url gets assigned before the launch of first page which is login page. I have a switch in my login page which if true, i need to set the different base url. But since the base url is set and the control doesnt come again to this module, i am not able to change it conditionally.
This is in my service.js
angular.module('sampleService', ['ngResource'])
.factory('sample', function ($resource, $rootScope) {
$rootScope.serviceUrl = "http://......";
...
});
This is in my app.js
var app = angular.module("sampleApp", ["sampleService"]);
This is how I am using $routeProvider
app.config(["$routeProvider", function ($routeProvider, $locationProvider) {
...
}]);
I want to change my service url conditionally as:
if(myflag)
$rootScope.serviceUrl = "url1";
else
$rootScope.serviceUrl = "url2";
I hope this will give some idea of what i want to do and what i am doing.
Thanks in advance.

I suppose you're using ngRoute in your application, right?
Maybe you should look into uiRouter where you control state. And what you're describing could fall into this category.
https://github.com/angular-ui/ui-router
Also read the differences between the two in this Stackoverflow content.

Yes uiRouter is best solution when it comes to dynamic page loading
Here is a simple PDF on how to use ui-sref in your code ,
Simple Example

Related

Angular.JS - Managing different states with same url

So here is a much needed requirement i need to implement and i know it should not be this way but this is a requirement i cannot waive off.
So currently i have a webapp of my own which has 3 different urls:
helloworld.com/en
helloworld.com/ar
helloworld.com/{coderName}
Now what i need to do is that when the url is /en or /ar, it should change the languages of the page which means it has to hit a different state. but whenever there is anything else apart from these two parameters, it should hit the third url i.e. /{coderName}.
Usually in node.js we can have routes set up in descending order in this way but how do we tackle this in angular.js?
If you want a default state, you can use the "otherwise". It is not what it supposed to do, but that's something you can use to get what you want.
Here is an example:
angular
.module('your module')
.config(function ($locationProvider, $stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise(function($injector){
let $state = $injector.get("$state");
$state.go('your default state');
});
}

How to deal with templates of completely different areas (but same website) with AngularJS

I have a webapp with a main index.html that shows each page through an ng-view and a routeProvider.
Now I'm adding an entry page for users who are still not logged in. This page could also have his own ng-view to slide different sections for non logged users (welcome, what is, sign in, sign up ecc...) and his own head with css scripts ecc...
I'd rather that both the webapp index and the entry page index address to www.example.com (so nothing like www.example.com/welcome ).
I thought about a structure similar to this:
webapp/
main/
page1/
page2/
welcome/
section1/
section2/
index.html
welcome.js (angular module for the entry page)
.htaccess
index.html
webapp.js (angular module containing the routeProvider for the webapp)
Currently I have that .htaccess that rewrites all the fake queries to index.html so that everything is handled here.
So in particular:
1) How can I say to the routerProvider of webapp.js to go to /welcome/index.html when the user is not logged in, if I already use this condition for the webapp main page? (Should I use the run method? a brief example will be helpful)
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when(...)
.when('/', {
templateUrl : 'main/webapp-main.html'
})
.when(...)
2) How do I prevent that everything in welcome/index.html will be loaded within the index.html ng-view? (maybe using ng-if to hide ng-view? or there is some way to control this behavour with the routerProvider?)
3) There is a better and simpler way to achieve all of this?
Thanks.
Update:
Ok I think there was an underlying problem in my question... I can't use a complete different page since everything is loaded in and switching to another page will cause the reload of the app loosing all the data.
So I suppose I should use the same main template for the entire website.
Then I add: there is a way in angularjs to load different style sheets dynamically?
this questions is old but i think is valid and can clarify someone a few thinks.
First of all you are suppose to use a single page for AngularJS apps, otherwise you will have to do something like a redirect link, and in your other-index.html load an entirely different Angular Application also loading every script needed in the first one.
1) Use ui-router is easy to work, and very robust, the only thing you need to have is a container for your ui-view then the ui-router will fill the container with the corresponding html
2) To prevent navigation you should do something like this:
angular.module('myApp', [])
.run(function($rootScope, mySessionService){
$rootScope.$on('$stateChangeStart',
function(event, next, nextParams, prev, prevParams) {
// The info of your currentUser could be obtain from a service
// or localStorage or cookies anyway you are already doing it
var authorized= checkAuthorization(next.authorazedRoles,
mySessionService.getCurrentRol());
if(!authorized) {
$rootScope.$state.go('defaultState');
// Or $rootScope.$emit('NOT_AUTHENTICATED');
// and some service will have to implement a listener for this emit
// $rootScope.$on('NOT_AUTHENTICATED', func..redirect to X State)
}
});
});

Hash removed from default routing in AngularJS

I'm writing an angular app where I need to accept an URL with a fragment hash (OAuth 2.0). Making it short it looks like this.
http://example.com/#access_token=918f4d6e90b25b13ef66a
When this URI is loaded, the routing process does not recognize the path and and it correctly redirects the app to the default route. The problem is that in thi way I loose the hash and I can't parse it anymore.
What I want to do is to parse the hash before it gets removed.
Do you have any idea on a possible solution?
Thanks.
P.S. In this app I can't use HTML5 mode. With it enabled it works just fine.
You just need to define an extra route to "catch" and save the access-token, before redirecting to another route.
E.g.:
$routeProvider
...
.when('/access_token=:accessToken', {
template: '',
controller: function ($location, $routeParams, AuthService) {
AuthService.login( // `AuthService` will save the token
$routeParams.accessToken); // The token is available in `$routeParams
// under the key `accessToken`
$location.path('/'); // Redirect to the default route
$location.replace(); // For better UX, remove this route from history
}
})
See, also, this short demo.
Or navigate directly to this URL for a live demo:
http://fiddle.jshell.net/ExpertSystem/N8CgC/show#access_token=12345.

Problems with AngularJS $location.path

I am having fun and games with a troublesome AngularJS route, so lets see if I can explain this as well as I can.
APP.JS:
app = angular.module("index", []);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/booking/damage/:regnumber', {
templateUrl: 'damage',
controller: 'DamageCtrl'
}).
otherwise({
redirectTo: '/'
});
}
]);
app.controller('IndexCtrl', function($scope, $location) {
$scope.regnumber = '';
$scope.progress = function() {
if ($scope.regnumber !== '') {
$location.path('/booking#/damage/' + $scope.regnumber);
} else {
$location.path('/booking#/damage');
}
};
});
My initial page has a path of
http://localhost/windscreens/glass/index#/index
and within this page is a form that via ng-submit="progress() calls the $scope.progress function within my IndexCtrl controller. There is a field in the form of ng-model="regnumber".
So when filling in the input field with lets say "ABC" and clicking on the button, I'd expect the path to become:
http://localhost/windscreens/glass/booking#/damage/ABC
But it becomes
http://localhost/windscreens/glass/index#/booking%23/damage/ABC
Thing is I am still really becoming used to the Angular routing system and haven't quite got it yet. Any advice on this will be appreciated!
Why am I seeing what I am seeing? What have I got wrong here?
The Angular $routeProvider can only change the part of the URL after the hash (#), so when calling $location.path(), you just use a plain URL fragment like you defined in the route for DamageCtrl.
Some explanation
I'm going to simplify a bit here, but hopefully it will help you understand what's going on.
You're making a SPA (single-page app), so the URL you enter in your browser to get into your app doesn't change while you navigate between routes; by default $routingProvider appends #/whatever/route to that base URL. In your case it looks like you have your entry point (ng-app) in a file called /windscreens/glass/index, so all routes will get appended to that.
Because you don't have an /index route defined that we can see, I'm not sure how http://localhost/windscreens/glass/index#/index is working for you. It should send you to http://localhost/windscreens/glass/index#/ because your otherwise route is just /.
Back to the question
If I understand your question correctly, I would make the index file (where ng-app lives) /windscreens/glass/index.html, then you can just enter http://localhost/windscreens/glass/ to get into the app, because the webserver will serve the contents of index.html by default.
At that point, your index page URL would become http://localhost/windscreens/glass/#/, and your /booking/damage/ routes would be http://localhost/windscreens/glass/#/booking/damage/ABC etc. The code to navigate to them would then be
$location.path('/booking/damage');
Angular routing changes the route on the page; it doesn't take you to a new directory or page.
So if index.html contains your Angular app and you have routes for "booking", "reservation", "cancellations", etc. You'll end up with urls that look like:
/glass/index.html#/booking
/glass/index.html#/reservation
/glass/index.html#/cancellations
The route merely appends itself to the index.html.
So, in a sense, your routes are working correctly. The %23 that you see being added is the url encoded # sign.
If you have a second Angular app that is found at /glass/booking and you're trying to forward the user to it, you can use $window.location.hash and $window.location.pathname. For example,
$window.location.hash = "/damage/ABC";
$window.location.pathname = "/windscreens/glass/booking";
should take you to:
/windscreens/glass/booking#/damage/ABC

Updating URL in Angular JS without re-rendering view

I'm building a dashboard system in AngularJS and I'm running into an issue with setting the url via $location.path
In our dashboard, we have a bunch of widgets. Each shows a larger maximized view when you click on it. We are trying to setup deep linking to allow users to link to a dashboard with a widget maximized.
Currently, we have 2 routes that look like /dashboard/:dashboardId and /dashboard/:dashboardId/:maximizedWidgetId
When a user maximizes a widget, we update the url using $location.path, but this is causing the view to re-render. Since we have all of the data, we don't want to reload the whole view, we just want to update the URL. Is there a way to set the url without causing the view to re-render?
HTML5Mode is set to true.
In fact, a view will be rendered everytime you change a url. Thats how $routeProvider works in Angular but you can pass maximizeWidgetId as a querystring which does not re-render a view.
App.config(function($routeProvider) {
$routeProvider.when('/dashboard/:dashboardId', {reloadOnSearch: false});
});
When you click a widget to maximize:
Maximum This Widget
or
$location.search('maximizeWidgetId', 1);
The URL in addressbar would change to http://app.com/dashboard/1?maximizeWidgetId=1
You can even watch when search changes in the URL (from one widget to another)
$scope.$on('$routeUpdate', function(scope, next, current) {
// Minimize the current widget and maximize the new one
});
You can set the reloadOnSearch property of $routeProvider to false.
Possible duplicate question : Can you change a path without reloading the controller in AngularJS?
Regards
For those who need change full path() without controllers reload
Here is plugin: https://github.com/anglibs/angular-location-update
Usage:
$location.update_path('/notes/1');
I realize this is an old question, but since it took me a good day and a half to find the answer, so here goes.
You do not need to convert your path into query strings if you use angular-ui-router.
Currently, due to what may be considered as a bug, setting reloadOnSearch: false on a state will result in being able to change the route without reloading the view. The GitHub user lmessinger was even kind enough to provide a demo of it. You can find the link from his comment linked above.
Basically all you need to do is:
Use ui-router instead of ngRoute
In your states, declare the ones you wish with reloadOnSearch: false
In my app, I have an category listing view, from which you can get to another category using a state like this:
$stateProvider.state('articles.list', {
url: '{categorySlug}',
templateUrl: 'partials/article-list.html',
controller: 'ArticleListCtrl',
reloadOnSearch: false
});
That's it. Hope this helps!
We're using Angular UI Router instead of built-in routes for a similar scenario. It doesn't seem to re-instantiate the controller and re-render the entire view.
How I've implemented it:
(my solution mostly for cases when you need to change whole route, not sub-parts)
I have page with menu (menuPage) and data should not be cleaned on navigation (there is a lot of inputs on each page and user will be very very unhappy if data will disappear accidentally).
turn off $routeProvider
in mainPage controller add two divs with custom directive attribute - each directive contains only 'templateUrl' and 'scope: true'
<div ng-show="tab=='tab_name'" data-tab_name-page></div>
mainPage controller contains lines to simulate routing:
if (!$scope.tab && $location.path()) {
$scope.tab = $location.path().substr(1);
}
$scope.setTab = function(tab) {
$scope.tab = tab;
$location.path('/'+tab);
};
That's all. Little bit ugly to have separate directive for each page, but usage of dynamic templateUrl (as function) in directive provokes re-rendering of page (and loosing data of inputs).
If I understood your question right, you want to,
Maximize the widget when the user is on /dashboard/:dashboardId and he maximizes the widget.
You want the user to have the ability to come back to /dashboard/:dashboardId/:maximizedWidgetId and still see the widget maximized.
You can configure only the first route in the routerConfig and use RouteParams to identify if the maximized widget is passed in the params in the controller of this configured route and maximize the one passed as the param. If the user is maximizing it the first time, share the url to this maximized view with the maximizedWidgetId on the UI.
As long as you use $location(which is just a wrapper over native location object) to update the path it will refresh the view.
I have an idea to use
window.history.replaceState('Object', 'Title', '/new-url');
If you do this and a digest cycle happens it will completely mangle things up. However if you set it back to the correct url that angular expects it's ok. So in theory you could store the correct url that angular expects and reset it just before you know a digest fires.
I've not tested this though.
Below code will let you change url without redirection such as: http://localhost/#/691?foo?bar?blabla
for(var i=0;i<=1000;i++) $routeProvider.when('/'+i, {templateUrl: "tabPages/"+i+".html",reloadOnSearch: false});
But when you change to http://localhost/#/692, you will be redirected.

Resources