Angular, ng-href make the page to refresh - angularjs

I am using ng-route in angularjs to switch beteen views , I made it to work, sample code below:
Html:
Mappings
New Products
angularjs
.config(function ($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "/MbfProduct/Main"
})
.when("/Mappings", {
templateUrl: "/Mappings"
})
.when("/Products", {
templateUrl: "/Products"
})
})
So everything is OK just I had to add the "#" in the ng-href attribute so the page doesn't get refreshed.
So my question how can I have the result, I mean no page refresh, without having the '#' in the href ?

you can write a function in your controller that changes the view. You have to use $location provider to switch between views. There is a method named path that does the switching.
Something like this.
app.controller("TestCtrl", function($scope, $location){
$scope.changeView = function(){
$location.path("/Mappings");
}
})
and call changeView function on ng-click of anchor tag and just remove the ng-href tag altogether. If that doesn't work you can use ng-href="javascript:void(0)" as well to give a void link to anchor tag.

Related

How to hide exact url call of $routeProvider from user

Well, I've implemented angularJS and I am calling different views which is being handled by $routeProvider . The problem is that for eg:
$routeProvider.
when('/prodDetails/:prodID', {
templateUrl: 'templates/productDetails.html',
controller: 'ProductController'
}).
Now, if I click on:
<a ng-href="#prodDetails/{{ prod.id }}">View Product</a>
The browser url will show prod.id in the url tab. How can I manipulate url to hide sensitive info in it.
Use Angular UI Router. it will solve your problem without doing anything. you can then pass parameter using params object given by angular-ui-router.
You can use angular ui router
You can achieve that by doing:
$stateProvider.
state('productDetail', {
url: '/prodDetails',
templateUrl: 'templates/productDetails.html',
controller: 'ProductController',
params: {
productId: 'defaultId'
}
})
And in the html:
<a ui-sref="productDetail({productId: prod.id})">View Product</a>
You can have access to the productId from the controller with the service $stateParams.
EDIT:
Let's say you have a encodeId and a decodeId functions:
<a ui-sref="productDetail({productId: encodeId(prod.id)})">View Product</a>
and in the controller:
app.controller(function($stateParams) {
var id = decodeId($stateParams.productId);
});

Override AngularJS route to display template based on $scope variable

Using Angular I have a dozen or so routes setup similar to the following example code.
Is there a way to override which template and controller is loaded based on some other criteria while keeping the URL in tact? My goal is to display a login page when... lets say $scope.isLoggedIn = false. I don't want to change the URL to /login.
SomeApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/place', {
templateUrl: 'routes/place.html',
controller: 'PlaceCtrl'
})
.when('/test', {
templateUrl: 'routes/test.html',
controller: 'TestCtrl'
});
}]);
ngRoute is a very simple library that can basically only maps urls to controller/views. If you want more flexibility, try ui-router which has the ability to route based on state.
This isn't really doable with ngRoute, but with ui-router you can dynamically provide different templates based on just about anything you want.
$stateProvider.state('root',
url: '/'
controller: 'HomePageController'
templateProvider: [
'$rootScope'
'$templateCache'
'$http'
($rootScope, $templateCache, $http) ->
templateId = if $rootScope.isLoggedIn then "home-page-logged-in" else "home-page-not-logged-in"
templateId = "/templates/#{templateId}.html"
return $http.get(templateId, cache: $templateCache)
]
)
The catch is, as far as I know, you can't change the controller, only the template. Which kinda stinks.

AngularJs with routes and anchor tags, working on second click

I have a simple view representing a simple menu which should be using anchor behavior. On the same page there's a bunch of H2 tags with id that the links should scroll to.
I'm using the $anchorScroll and $location.
THE ISSUE: The first time I click a link, I can see that the route is updated, e.g.:
http://localhost:60002/#!/docs/view/somedoc#someResourceId
But it triggers a route, the SECOND time I click it, it behaves as expected.
UPDATE: It's not the anchorScroll() did it manually using element.scrollIntoView(true) same behavior. If I don't use $location.hash it works, but then I loose the possibility of linking to anchors.
Any ideas?
VIEW:
<div ng-controller="DocsMenuCtrl">
<ul ng-repeat="menuItem in menuItems">
<li><a ng-click="foo(menuItem.resourceId)">{{menuItem.title}}</a></li>
</ul>
</div>
...
...
<h2 id="...">Test</h2>
...
CONTROLLER:
module.controller('DocsMenuCtrl', ['$scope', '$http', '$location', '$anchorScroll', 'session', function ($scope, $http, $location, $anchorScroll, session) {
$scope.foo = function (resourceId) {
$location.hash(resourceId);
$anchorScroll();
};
$http.get('/api/menu/').success(function (d) {
$scope.menuItems = d;
}).error(function () {
session.logger.log(arguments);
});
}]);
ROUTEPROVIDER CONFIG etc
$locationProvider.hashPrefix('!');
$routeProvider
.when('/default', {
templateUrl: 'clientviews/default',
controller: 'DefaultCtrl'
})
.when('/docs/view/:id', {
templateUrl: 'clientviews/docs',
controller: 'DocsCtrl'
})
.otherwise({
redirectTo: '/default'
});
$location does not reload the page even if it is used to change the url. See the "What does it not do?" section of this page: $location ngDoc.
As Ganonside said, the location service does not reload the url. Once you are certain that the url changes you can use the route service, specifically $route.reload() to trigger your routing.
The best solution I've found is here: https://github.com/angular/angular.js/issues/1699#issuecomment-22509845
Another option, if you don't use search params, is to tell the route provider not to reload on hash or search changes (unfortunately, it is one option for both).
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/group/:groupName', {
templateUrl: '/templates/groupView.html',
reloadOnSearch: false
}).otherwise({redirectTo: '/'});
}]);

$routeProvider not firing Controller

I have a situation where the Angular $routeProvider appears to not fire controller actions on route changes.
The routes are super simple urls:
window.app = angular.module('app', ['ngRoute', 'app.filters', 'app.services', 'app.directives', 'app.controllers'])
.config([
'$routeProvider', function($routeProvider) {
console.log("app.js config launched");
$routeProvider
.when('/nav', {
templateUrl: 'temp/test.html',
controller: 'navController'
// controller: function($scope) { alert('scope called.') }
})
.when('/home', {
controller: 'homeController',
template: ' '
});
$routeProvider.otherwise({ redirectTo: '/home' });
}
]);
The controller is just an log out to verify access:
app.controller('navController', [
"$scope", "cellService",
function ($scope, cellService) {
console.log("**** navController fired");
}
]);
The initialization code fires so the routing is initialized. When I hit:
http://localhost:4333/app/#/nav
and the url changes I can see that the test.html template is accessed by the browser, but the controller never fires.
This seems to indicate the route is getting activated by the URL change, but for some reason the controller is not firing. I've tried using a function instead of a controller name, but that too never gets fired. I've also verified that the controller is valid by attaching ng-controller="navController" to an element and that fires the controller just fine.
This is a page that originally didn't have routing associated as it was basically single self-contained page that didn't need navigation. I added the route code after the fact. I added an ng-view (there wasn't one before) after which at least the template started loading - without ng-view nothing happens.
Stumped and not sure what else to look at. Help.
It turns out the problem really was operator error on my part, but I think it's a scenario that can cause issues so I'll use this as the answer.
The issue that caused this problem were two-fold:
The HTML template HTML page (via templateUrl) had an invalid URL so the page never loaded
and the controller wasn't fired because of that.
When switching to a template I used an empty template (" ") but had also
removed the ng-View directive. The ng-View directive MUST BE present
even when using an empty template. Without it the controller doesn't fire.
In both cases it didn't work and I mistakenly assumed that the controller was not getting fired which was confusing because it did fire if I explicitly hooked it up with ng-controller.
Yup plain operator error, but the latter is vitally important - without ng-View the controller doesn't fire.
What happens if you define the function externally and reference that? So instead of
.when('/nav', {
templateUrl: 'temp/test.html',
controller: 'navController'
})
It would be
.when('/nav', {
templateUrl: 'temp/test.html',
controller: navController
})
and elsewhere
function navController($scope, cellService){
console.log("**** navController fired");
}
navController.$inject = ['$scope', 'cellService'];

AngularJS $location not updated properly when using $routeProvider

I have an Angular JS application with a defaultController which controls the header of the app. Then I have some other controllers one for each view. The views are loaded in the <main>. I load the views using the $routeProvider with this code:
myapp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/login', {
templateUrl: 'templates/login.html',
controller: 'loginController'
}).
when('/dashboard', {
templateUrl: 'templates/dashboard.html',
controller: 'dashboardController'
}).
...
I am trying to display a LOGOUT button inside the header when the loaded view is the dashboard and hide it if the loaded view is the login view. In order to do that I have on the defaultController the $location object and I properly add and remove classes from the LOGOUT button with ng-class.
There is only one problem: $location gives me the correct path the first time I load the page, but after I change the view (changed by the $routeProvider) that variable is not updated anymore, so when I am actually on /#/dashboard , the $location.url is still on /login. Here the controller code:
controllers.controller('defaultController', ['$scope', 'ipCookie', '$location', function($scope, ipCookie, $location) {
$scope.url = $location.url();
...
I also tried with $window.location.hash with the same result.
Any idea?
EDIT: after the accepted answer this is what I ve added on the defaultController in order to make it work
$scope.$on("$locationChangeSuccess", function() {
$scope.url = $location.url();
});
The location is probably updated in the service after your default controller is loaded.
You can either inject the $location service into the scope and make decisions in your template based on it (then it will automatically be watched and re-evaluated) or you could listen for the $locationChangeSuccess event.
When injecting, you can simply $scope.location = $location and then use something like <a ng-hide="location.path() != '/something'">.
$location broadcasts the $locationChangeSuccess on the root scope, so you should be able to listen for it on whichever scope you have available: $scope.$on( "$locationChangeSuccess", function() { /* do something */ } );

Resources