Angular ngRoute: How to temporarily disable reloadOnSearch? - angularjs

In AngularJS 1.4.8 with ngRoute, I am trying to capture search parameters from the URL and then clear them from the URL without reloading the route. This can be achieved easily enough by setting reloadOnSearch: false in my route config. However, after clearing the search parameters from the URL, I do want my route to reload on search.
Is it possible to temporarily enable/disable reloadOnSearch, or do I need to disable it and then manually trigger a reload using $route.reload()?
Here is my current configuration:
angular.module('myApp', ['ngRoute'])
.config(routeConfig)
.controller('MyViewController', MyViewController)
;
function routeConfig($routeProvider) {
$routeProvider
.when('/', {
controller: 'MyViewController',
controllerAs: 'myView',
reloadOnSearch: false,
template: '<h1>Search Params</h1><ul><li ng-repeat="(key, value) in myView.params">{{key}}: {{value}}</li></ul>'
})
.otherwise('/')
;
}
function MyViewController($location) {
var myView = this;
myView.params = $location.search();
$location.search({});
}
Ideally, after calling $location.search({}); I would like to set reloadOnSearch: true.

Related

AngularJS page blank after refresh

I am building a web aplication with AngularJS. I am using ui-router and I have defined states like this:
//appContacts.js
(function () {
"use strict";
var app = angular
.module('appContacts', ['ui.router', 'angularUtils.directives.dirPagination'])
.config(['$stateProvider', '$locationProvider', '$urlRouterProvider',
function ($stateProvider, $locationProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("home", {
url: "/",
templateUrl: "views/contactsView.html",
controller: "contactsController",
controllerAs: "vm"
})
.state("organization", {
url: "/organizations/:Id",
templateUrl: "views/organizationDetail.html",
params: { Id: null },
controller: "organizationsController",
controllerAs: "vm"
})
.state("contact", {
url: "/contact/:Id",
templateUrl: "views/contactDetails.html",
params: { Id: null },
controller: "contactsDetailController",
controllerAs: "vm"
})
$locationProvider.html5Mode({
enabled: true,
requireBase: false,
rewriteLinks: true
});
$locationProvider.html5Mode(true);
}
]);
})();
I get requested information from the Database using HTTP methods. I have two issues:
When I refresh the page the page get blank. Any idea what I am doing wrong?
The home page controller calls automatically the HTTP methods that populate a table using ng-repeat. That means that it is impossible to visit another page directly like http://localhost:50895/contact/the-id because there is not data stored. I always have to visit the home page to load the data. How could I save and make available that data to all pages/states/controllers?
EDIT:
I have 4 error shown in the console.
Could you please debug it and check the browser console for any errors or exceptions??
There are three ways in which you can pass the data around:
a) Use $rootScope , but this is not considered as proper coding standard
b) Make use of the inbuilt .service() provided by AngularJs, this is a singleton object, means the value set into it in the first controller can be used anywhere down the line. But the value will be erased if you refresh the page.This is considered as better coding standard than using $rootScope
c) You can make use of localStorage or sessionStorage, using this the data can be retrieved even after the page refresh. Data will be stored as string, so parsing is needed.
There is one more way to store the data , Cookies. But this is used to store small string values.

AngularJS - load data before loading any controller

I'm making a single page application (SPA). I made a controller called InitialControler to load the data from the server at this url (local.app/init).
I want this url to be opened before any other url. I'm using ui-router, I did a $state.go('init') in the .run() function but it still load the requested page before the 'init' page
First create state called app
$stateProvider.state('app', {
abstract: true,
templateUrl: "assets/partials/container.html",
controller: 'AppCtrl',
resolve: {
init: function(MyFactory) {
return MyFactory.resolver();
}
}
});
Now, any new state you create should be child state of app state. This is also good because it become sort of your root scope. And state will not process unless your factory resolves.
This is how you create your factory
app.factory('MyFactory', function($http){
var items = [];
return {
resolver: function(){
return $http.get('my/api').success(function(data){
items = data;
})
},
get() {
return items;
}
}
});
Now in any other state
$stateProvider.state('app.items', {
url: '/items',
templateUrl: "assets/partials/items.html",
controller: function($scope, MyFactory){
$scope.items = MyFactory.get();
}
});
More on sate resolve
https://github.com/angular-ui/ui-router/wiki#resolve
If you are using ui-router then you could resolve this using nested states. For example:
$stateProvider
.state("main", {
url: "/",
template: '<div ui-view></div>',
controller: 'InitController'
})
.state("main.landing", {
url: "landing",
templateUrl: "modules/home/views/landing.html",
controller: 'LandingPageController'
})
.state("main.profile", {
url: "profile",
templateUrl: "modules/home/views/profile.html",
controller: 'ProfileController'
});
In this example you have defined 3 routes: "/", "/landing", "/profile"
So, InitController (related to "/" route) gets called always, even if the user enters directly at /landing or /profile
Important: Don't forget to include <div ui-view></div> to enable the child states controller load on this section
One way to do is, in config declare only 'init' state. And in InitialController, after data is loaded(resolve function of service call), configure other states. But in this approach, whenever you refresh the page, the url will change to local.app.init.
To stay in that particular state even after reloading, the solution I found is to have a StartUp app in which I loaded the required data and after that I bootstraped the main app manually by angular.bootstrap.

Make AngularJS route accessible ONLY from application code / links

i want create a route for angularJs which will be accessible only from application code and links. The main idea is to prevent the user to access the page after directly typing route url in browser's location bar.
For route configuration i use "ngRoute" module's $routeProvider.
I can't find an answer for this question. Is the thing i need possible?
Thanks in advance.
You can listen $locationChangeStart event. In your routes you can set a parameter (I've called it "restricted" but you could call it whatever you want) like this:
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'MainCtrl',
template: 'Allowed from anywhere.<br>Go to main page',
restricted: false
})
.when('/main', {
controller: 'MainCtrl',
template: 'Allowed from anywhere.<br>Go to restricted page',
restricted: false
}).when('/restr', {
controller: 'RestrictedPageCtrl',
template: 'Allowed only from main',
restricted: '/main'
});
});
If it's false, that means there's no restriction, if it's set to a path, then the route is only accessible from that path. And you can check it with this:
app.run(function($rootScope, $location, $route) {
$rootScope.$on('$locationChangeStart', function(event, next, current) {
var nextRoute = $route.routes[$location.path()];
var currentPath = current.split('#')[1];
if (nextRoute.restricted && nextRoute.restricted !== currentPath) {
$location.path('/');
alert('You are trying to reach a restricted page!!!!');
}
});
});
You can change the behaviour and redirect user to another link or prevent location change with event.preventDefault();.
Note that if you are not using hashtag (#) in your links (html5Mode) you should change the way to get the current link.
Here's a plunker.

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.

Change route path without reloading controller and template in angularjs route

Hi all angularjs developer, I have followed the ng document (link) .I have searched since many times but i did not find any solution that will help me properly. I need to change route without reloading the controller and template. I have written a route that look like this below:-
$routeProvider
.when('/page1', {
templateUrl: 'page1',
controller: 'page1Ctrl',
caseInsensitiveMatch: true,
reloadOnSearch: false
})
.when('/page2', {
templateUrl: 'page2',
controller: 'page2Ctrl',
caseInsensitiveMatch: true,
reloadOnSearch: false
})
.when('/page3', {
templateUrl: 'page3',
controller: 'page3Ctrl',
caseInsensitiveMatch: true,
reloadOnSearch: false
}).otherwise({ redirectTo: '/index' });
Moreover, at first I go to the page1 then page2 then page3 after that now i want to go to the page1 without reloading or calling page1Ctrl and page1 template. Example: suppose when i was page1 that time i have worked something like i have selected an ng-grid record which was paging size 3 and i have inputted some fields. After that i go the page3 then i go to the page1 again. Now this time i want to see the page1 what i selected ng grid record and what i inputted. How can i solve this? Thanks.
I want to suggest to use Angular Ui.router
you will have the ability to change the state of routes , for more check the documentation
To persist data when moving away from a controller and then back again, the recommended Angular approach is to use services. See this NG-Conf talk: https://www.youtube.com/watch?v=62RvRQuMVyg.
To persist input fields and paging index when leaving page1Ctrl and then returning, for example, you could create a pagingModelService.
function PagingModelService($rootScope)
{
var pagingModelService = {};
////////////////////
// persisted data //
////////////////////
pagingModelService.pagingIndex;
pagingModelService.field1;
pagingModelService.field2;
////////
//Init//
////////
return(pagingModelService);
}
Then inject the service in the controller, and set the $scope values to the service:
function Page1Ctrl($scope, pagingModelServiceModel)
{
///////////////////////////////////////////////////
//set local $scope variables to persisted service//
///////////////////////////////////////////////////
$scope.pageIndex = pagingModelService.pagingIndex;
$scope.field1 = pagingModelService.field1;
$scope.field2 = pagingModelService.field2;
}
Also, you can look into angular-local-storage for persisting data: https://github.com/grevory/angular-local-storage

Resources