I want to get working back button of the browser with angular 1.4.10 ui-router.
This is sample code of my app.js
var myApp = angular.module("myApp",[ "ui.router", "AppCtrls"]);
myApp.config(function ($stateProvider, $urlRouterProvider, $locationProvider){
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$stateProvider.state("state1", {
url: "",
template: "<p>State 1</p>",
controller: "Ctrl1"
}).state("state2", {
url: "",
template: "<p>State 2</p>",
controller: "Ctrl2"
});
});
var ctrls = angular.module("AppCtrls", []);
ctrls.controller( "Ctrl1", function($scope) {
console.log("Ctrl1 loaded.");
});
ctrls.controller( "Ctrl2", function($scope) {
console.log("Ctrl2 loaded.");
});
When I am giving URL to each state back button works well but when I have not given any URL to each state back button is not working.
Is there any workaround to get back button working without having URL of state?
Related
I have a basic angularjs (1.8.2) application with the latest version of ui router (1.0.29).
The application will load and work fine but I have noticed in the console I get the following errors when I initially go to a state (using the ui-sref route) with a template url:
Transition Rejection($id: 0 type: 2, message: The transition has been superseded by a different transition, detail: Transition#2( 'home'{} -> 'page2'{} ))
It only happens the first time a user goes to a state with a template url, after that there are no more errors and the application continues to work.
Demo Here
All the information I have found online just says that I have a configuration error with ui router but all the documentation I have found shows that this should work without error.
Any help is appreciated, thanks.
var app = angular.module('plunker', ['ui.router', 'editor']);
// routing configuration
app.config(['$urlRouterProvider', '$stateProvider', function ($urlRouterProvider, $stateProvider) {
// default route
$urlRouterProvider.otherwise('/');
// available states
var states = [
{
name: 'home',
url: '/',
template: '<div><h3>HOME PAGE</h3></div>'
},
{
name: 'page2',
url: '/page2',
controller: 'page2Ctrl',
templateUrl: 'page2.html',
},
{
name: 'page3',
url: '/page3',
controller: 'page3Ctrl',
templateUrl: 'page3.html',
}
];
// Loop over the state definitions and register them
states.forEach(function (state) {
$stateProvider.state(state);
});
}]);
app.controller('mainCtrl', function($scope) {
$scope.content = 'World';
});
app.controller('page2Ctrl', function($scope) {
$scope.hasLoaded = true;
});
app.controller('page3Ctrl', function($scope) {
$scope.hasLoaded = true;
});
Error caused because there are 2 ui-sref for each state. Remove the one from li element and it works fine:
<li role="presentation" ui-sref-active="active">
<a ui-sref="home" ui-sref-opts="{reload: true, inherit: false}">
Home
</a>
</li>
I am trying to redirect to another route after an event, but it shows only url change (http://localhost:8000/login changed to http://localhost:8000/login#/home). I want to change it to http://localhost:8000/home#, but I can not figure out how to do that. And my route for this url not working.
app.js:
var app = angular.module('laravel', ['ngRoute'])
.constant('API_URL', 'http://localhost:8000/')
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/login', {
controller: 'authController',
templateUrl: 'resources/views/auth/login.blade.php',
})
.when('/home', {
templateUrl : "resources/views/home.bade.php",
controller : 'homeController'
})
.otherwise({
redirectTo: '/',
});
});
auth.js, containing my authController:
app.controller('authController', function ( $scope, $http, $location, API_URL){
$scope.login = function(){
var url = API_URL + "login";
$http.post(url, $scope.file).success(function (response) {
console.log("coming in homepage!!");
// sessionStorage.setItem('user', $scope.user);
$location.path('/home');
});
}
});
The above code just converts the URL http://localhost:8000/login to http://localhost:8000/login#/home.
You need something like this i guess
$location.path('/home').replace();
You can check API doc for $location.
I got it.
If you configure $location to use html5Mode (history.pushState), you need to specify the base URL for the application with a tag or configure $locationProvider to not require a base tag by passing a definition object with requireBase:false to $locationProvider.html5Mode():
$locationProvider.html5Mode({ enabled: true, requireBase: false});
//$locationProvider.html5Mode(true); //if we want to remove html5mode requirebase.
I've created a directive, called admin, which I only want to show if the base URL contains the string admin and then depending on the URL path the directive's view will show different content.
So if the user navigates to admin.example.com they will see the directive's view, they won't see it if they go to just example.com.
I've got it working to an extent, it works when I first load the angularJS app, but not when I click on different pages of the app and load different views and routes.
This is my basic App:
/* Define the `app` module */
var app = angular.module('app', ['ngRoute', 'ngTouch', 'ngAnimate', 'ui.bootstrap', 'ngSanitize']); // TODO: 'ngAnimate', 'ui.bootstrap'
app.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider){
$routeProvider
.when('/', {
class: 'home-page',
title: 'Home',
templateUrl: '/app/static/home.html',
controller: 'mainController as mainCtrl'
})
.when('/about', {
class: 'about-page',
title: 'About',
templateUrl: '/app/static/about.html',
controller: 'mainController as mainCtrl'
})
.when('/news/id-:newsId', {
class: 'news-page',
title: 'News',
templateUrl: 'app/components/news/details/newsDetailsView.html',
controller: 'newsDetailsController as newsDCtrl'
})
.otherwise({
class: 'page-not-found',
title: '404 Page Not Found',
templateUrl: '/app/static/404.html',
controller: 'mainController as mainCtrl'
});
// use the HTML5 History API
$locationProvider.html5Mode(true);
}]);
app.run(['$rootScope', function($rootScope) {
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
$rootScope.class = current.$$route.class;
$rootScope.title = current.$$route.title;
$rootScope.description = current.$$route.description;
});
}]);
app.controller('adminController', ['$location', function ($location) {
var adminCtrl = this;
adminCtrl.isAdmin = $location.host().includes('admin.example') ? true : false;
adminCtrl.urlPath = $location.url();
}])
app.directive('admin', [function(){
return {
restrict: 'E',
templateUrl: 'app/components/admin-links/adminView.html',
transclude: true,
replace: true,
controller: 'adminController as adminCtrl'
};
}]);
The problem is adminCtrl.urlPath = $location.url(); only updates when I refresh the page, not when I click on the different routes within the app and change the page without refreshing the page.
How can I get this value to update when the user navigates through the different views/routes without refreshing the page?
You need to use $location.path()
This will give you the route paths.
Change
adminCtrl.urlPath = $location.url();
to
adminCtrl.urlPath = $location.path();
We have an ASP.NET MVC 5 application which uses ui-router AngularJS module.
When we go back to a state that has already been loaded, it always shows the old data until we do a full page refresh.
For example:
User clicks 'View Profile', we show the "ViewProfile" state, a page displaying the profile
User clicks "Edit Profile", we show the "EditProfile" state, a page with fields to edit the profile
User makes changes and clicks 'Save', they are then moved back to the "ViewProfile" state
When "ViewProfile" state loads, it still shows the old data before the edits
How can we force ui-route to pull fresh data any time it loads any state?
Angular config
var app = angular.module("MyApp", ['ngIdle', 'ui.router'])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
// Configure client-side routing
$locationProvider.hashPrefix("!").html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('Home', {
url: '/',
views: {
"mainContainer": {
templateUrl: function (params) { return 'Home/Index'; }
}
}
})
.state('ProfileManagement', {
url: '/ProfileManagement-{action}',
views: {
"mainContainer": {
templateUrl: function (params) { return 'ProfileManagement/' + params.action; }
}
}
})
}]);
How we are doing the transition
$state.go(stateName, { action: actionName }, { reload: true, inherit: false, notify: true });
EDIT w/ Solution
Since all the functionality is written using jQuery, we cannot use Angular controllers to control the data. Our solution was to completely disable Angular template caching with the following code:
app.run(function ($rootScope, $templateCache) {
$rootScope.$on('$viewContentLoaded', function () {
$templateCache.removeAll();
});
});
By default ui-router state transition will not re-instantiate toState's controller.
To force instantiation of the controller, you can do this.
//assuming you are using $state.go to go back to previous state
$state.go('to.state', params, {
reload: true
});
You need to use resolves, like so:
var app = angular.module("MyApp", ['ngIdle', 'ui.router'])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
// Configure client-side routing
$locationProvider.hashPrefix("!").html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('Home', {
url: '/',
views: {
"mainContainer": {
templateUrl: function (params) { return 'Home/Index'; }
}
},
resolve: {
loadedData: (injectable) => injectable.getData()
}
})
.state('ProfileManagement', {
url: '/ProfileManagement-{action}',
views: {
"mainContainer": {
templateUrl: function (params) { return 'ProfileManagement/' + params.action; }
}
},
resolve: {
loadedData: (injectable) => injectable.getData()
}
})
}]);
In each state, there is a resolve, calling the method 'getData()' in the injectable service (I'm saying a 'service' because that's where we would have the data loaded from).
Then for each state's controller, it will have access to the loadedData resolve; the data will already be loaded at that point and be usable by that controller. So for your case scenario, going back to the state you've come from, the newly updated data will be loaded again and available in that state again.
Keep your state transition the same, with the reload: true, as that is what you want as well.
Maybe this work for your problem.
In your angular main page you should have something like this:
app.run(['$rootScope', function ($rootScope){
$rootScope.$on('$stateChangeStart', function(event, toState){
$rootScope.UrlActive=toState.name;
});
}]);
In your angular controller you should have something like this:
app.controller('AnalisisCtrl', ['$scope','$rootScope', function ($scope,$rootScope) {
$scope.$watch('UrlActive', function(newValue) {
if(newValue="ProfileManagement"){
doSomething();
};
});
}]);
I am using Angularjs ui-router ui-bootstrap tabs.
It works on http://plnkr.co/edit/EYLsPRlxEXQP4HsXuPKK?p=info but does not work on my website. The active tabs does not get highlighted when clicked. The correct content loads though.
var app = angular.module('Plunker', ['ui.router', 'ui.bootstrap'])
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('tab1', {
url: '/tabpage1',
templateUrl: 'tab1.html',
controller:'tabsController'
})
.state('tab2', {
url: '/tabpage2',
templateUrl: 'tab2.html',
controller:'tabsController'
})
.state('tab3', {
url: '/tabpage3',
templateUrl: 'tab3.html',
controller:'tabsController'
})
$urlRouterProvider.otherwise('/');
});
app.controller('tabsController',['$scope','$state',function($scope, $state){
$scope.tabs = [
{ title: 'Announcements', route:'tab1', active:false},
{ title: 'Course Info', route:'tab2', active:true},
{ title: "Timetable", route: "tab3", active: false },
];
}]);
Can anybody kindly advise?
Thank you.