AngularJs get route by URL - angularjs

Is there a way to get route by URL??
What I mean is I have a route /users/:id, I am getting route object using $route
var route_object = ($route.routes['/users/:id']);
But is it possible to get route with this URL /users/5
So when I try
var route_object = ($route.routes['/users/5']);
I am getting undefined value.

No, there is no build-in way to get a route object by corresponding url. However it's pretty easy to do with few lines of code. The idea is to test url against routes regular expressions:
var url = '/users/5/';
for (var path in $route.routes) {
if ($route.routes[path].regexp && $route.routes[path].regexp.test(url)) {
console.log('found route:', $route.routes[path]);
}
}
You can wrap it in helper function and put in in some util service maybe or controller:
function getRouteByUrl(url) {
for (var path in $route.routes) {
if ($route.routes[path].regexp && $route.routes[path].regexp.test(url)) {
return $route.routes[path];
}
}
return null;
}

Related

Changes to $location service are not getting reflected into the browser address bar

I have a function as below which is used to route to particular pages. The issue here is $location.url(url).search(search); is getting executed and I can see the changes reflected in debugger, but the changes are not getting reflected into the browser address bar.
var routeToPage = function (page, search) {
if (angular.isDefined(page) && null !== page) {
var url = page;
url = url.substring(url.length-1) === '/'? url.substring(0, url.length-1): url;
$timeout(function () {
if (search) {
$location.url(url).search(search);
} else {
$location.url(url);
}
});
}
};
I tried $window.location.assign(url); and its working fine but I need search parameters also. Any help will be greatly appreciated.
Add $scope.apply after $location.url(url).search(search);

Using Laravel 5.4 route in AngularJS $http service

I'm using Laravel 5.4 and AngularJS. I have this function :
$scope.allPosts = function() {
$http.get("/posts")
.then(function(){
}, function(error){
});
};
How can I avoid using hardcoded "/posts" and instead using a Laravel route there ?
Thank you.
Simply share your routes variable on app as Json object and call them using a common function. but you should only share web app related routes.
view::share('routes',json_encode($routeArray));
in the header file of app
var routes = {{$routes}}
Create functions to access routes from routes.js
function getRoute(key) {
var results = fetchFromObject()
if(results === false){
return f
}else if (typeof results === 'undefined') {
return f
}else{
return results
}
}
function fetchFromObject(obj, prop) {
if(typeof obj === 'undefined') {
return false;
}
var _index = prop.indexOf('.')
if(_index > -1) {
return fetchFromObject(obj[prop.substring(0, _index)], prop.substr(_index + 1));
}
return obj[prop];
}
now call in your app getRoute('key')
You can use the laroute package to get Laravel's routes in your JS:
$http.get(laroute.route('posts'));

How to add dynamic open routes in Angular?

In my Angular app I a restricting redirects with the following code within run() in my app.js
var restrictedPage = $.inArray($location.path(), ['/login', '/register']) === -1;
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage && !loggedIn) {
$location.path('/login');
}
I would want to add /route/action/:myParameter also to be added as a part of login and register, where myParameter is a variable.
Is there a way I can achieve this?
If you want to do this manually, you can run the following against the $location.path() variable.
var toFind = '/route/action/'
var path = $location.path()
if (path.substring(0, toFind.length) === toFind) {
var myParameter = path.substring(toFind.length)
...
}
If you have more than one route like this however, consider using angular-route, which allows nicer syntax, eg:
routeProvider.when('/route/action/:myParameter', ...)

angular ui-router go to URL

How to use $state.go() if I have just the URL ?
Or can I get a state based on URL? (and than use $state.go(state))
I'm asking because I had to intercept the $urlRouterProvider.otherwise() to wait for an other plugin loads some external modules.. and now I need to continue and call the URL that call otherwise()
In place of $state.go(), you can use $location service as well.
i.e.
$location.path(url)
Please take care of not using # in URL. You can also use window.location.href
I had a similar problem, and $location wasn't helping, so I wrote a function to get the state from the url.
NB: I am using nested states based on ui-router.stateHelper, so I traverse my nested states object, testing for url matches. It would be slightly different when using dot notation to define nested states - and even easier if you don't use nested states at all!
function goPath (path) {
var target;
var arr = path.match(/\/\w+/g);
var i = 0;
var testState = function (state, i) {
if (state.url === arr[i]) {
target = state;
if (state.children && state.children.length && arr.length > i+1) {
i++;
state.children.forEach( function (childState) {
testState(childState, i);
});
}
}
};
myStatesObj.forEach( function (state) {
testState(state, i);
});
$state.go(target.name);
};
I was on a similar situation, what I did is changed the location to a different path and reset it to the current after a timeout like this
var path = $location.path();
$location.path("/");
$timeout(function(){
$location.path(path).replace(); //use .replace() so the empty path won't go to the history
},0);
i'm adding a full answer to this due to the high number of views.
NOTE: location.search() is only used where you need to handle a URL with a query string in it. otherwise use location.path() only.
your ui.router login state should look something like ...
.state('login', {
url: '/login',
templateUrl: 'routes/login/login.html',
controller: 'LoginController',
controllerAs: 'loginCtrl',
authenticate: false,
params: {
fwdPath: undefined, // Location to forward to on login success
fwdQueryStringObject: undefined // Query string object to use on login success - retrieved from $location.search()
}
})
your 401 (unauthorised) interceptor should look something like ...
state.go('login', {fwdPath: location.path(), fwdQueryStringObject: location.search()});
your login controllers login function should call your login service's login function. the code INSIDE the controllers login function should look something like ...
loginService.login(self.username, self.password).then(function (response) {
// local vars prevent unit test failure
var fwdPath = state.params.fwdPath;
var fwdQueryStringObject = state.params.fwdQueryStringObject;
if (response.status === 200) {
timeout(function () {
if (fwdPath != null) {
location.path(fwdPath).search(fwdQueryStringObject);
location.replace();
} else {
state.go('home');
}
}, 400);
} else {
self.error = true;
}
self.pending = false;
}
};
and finally your unit tests ...
state.params.fwdPath = '/login/list';
state.params.fwdQueryStringObject = {q: 5};
spyOn(location, 'path').and.callThrough();
spyOn(location, 'search').and.callThrough();
...
expect(location.path).toHaveBeenCalledWith('/login/list');
expect(location.search).toHaveBeenCalledWith({q: 5});

Disable template caching in AngularJS with ui-router

I have noticed that from time to time I'll make a change to one of the templates within my AngularJS application and that at runtime, the change won't be visible. Rather, I'll have to refresh the application and if that fails, go to the path of the template itself and refresh it in order to see this change.
What's the best way to prevent caching of these templates like this? Ideally, I'd like them to be cached during the current use of the Angular application, but that the next time I load the page, they retrieve the latest and greatest templates without having to manually refresh.
I'm using ui-router if that makes any difference here. Thanks!
You can use a decorator and update UI Router's $templateFactory service to append a suffix to templateUrl
function configureTemplateFactory($provide) {
// Set a suffix outside the decorator function
var cacheBuster = Date.now().toString();
function templateFactoryDecorator($delegate) {
var fromUrl = angular.bind($delegate, $delegate.fromUrl);
$delegate.fromUrl = function (url, params) {
if (url !== null && angular.isDefined(url) && angular.isString(url)) {
url += (url.indexOf("?") === -1 ? "?" : "&");
url += "v=" + cacheBuster;
}
return fromUrl(url, params);
};
return $delegate;
}
$provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}
app.config(['$provide', configureTemplateFactory]);
Above solution was great and was not working for template urls
function templateUrl: function($stataParams) { return '/serverUrl?id=' + $stataParams.id + '&cid=' + $stataParams.cid; }
fixed by
function templateFactoryDecorator($delegate) {
var fromUrl = angular.bind($delegate, $delegate.fromUrl);
$delegate.fromUrl = function (url, params) {
if (url !== null && angular.isDefined(url)) {
if (typeof url == 'function') {
url = url.call(url, params);
}
if (angular.isString(url)) {
url += (url.indexOf("?") === -1 ? "?" : "&");
url += "v=" + Date.now().toString();
}
}
return fromUrl(url, params);
};
return $delegate;
}

Resources