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.
Related
I am trying to implement a tabbed interface akin to this: http://odetocode.com/blogs/scott/archive/2014/04/14/deep-linking-a-tabbed-ui-with-angularjs.aspx
However, on my state change, the controller of the parent state seems to be reinitialized (or a new $scope is created?)
There are two major differences between the example plunkr and my project.
I use a parameter in my url
I resolve different data on the state change for each tab (removing this does nothing).
I am not using ui-bootstrap for the tabs but am triggering a $state.go on ng-click of the tab.
I experimented with the above plunkr and added a dropdown to the parent state; however the parent dropdown values seem to persist when the child states change. I am not too concerned with the child states and will probably end up using sticky states anyways.
I am using wondering if I am doing something fundamentally wrong before I try and add another package to my project.
here is a rough plunkr of what I am trying to do: http://plnkr.co/edit/TmRQN5K8OEc8vHG84G5z?p=preview
here is my config:
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.when('/main',
function ($state) {
$state.go('parent.tab1', { main_id: '00008' });
});
$stateProvider
//Handle States Here
.state('parent', {
abstract: true,
url: '/parent?main_id',
templateUrl: "main.html",
controller: 'Main_Controller',
resolve: {
//Calls to API
}
})
.state('parent.tab1', {
url: "/applications",
templateUrl: "tab1.html",
controller:'Tab1Ctrl',
resolve: {
//Get some different data from an API
},
})
.state('parent.tab2', {
url: "/phasing",
templateUrl: "tab2.html",
controller: 'Tab2Ctrl',
resolve: {
//More API Data
}
});
});
I've made your plunker working here
$urlRouterProvider
//.when('/main',
.when('',
function ($state) {
$state.go('parent.tab1', { main_id: '00008' })
});
Also there is a change in main.html, which does not use ng-controller any more. We just have to pass the proper Controller name
$stateProvider
//Handle States Here
.state('parent', {
abstract: true,
url: '/parent?main_id',
templateUrl: "main.html",
controller: 'MainController',
resolve: {
//Calls to API
}
})
...
// MainController
// these two names should fit
app.controller("MainController", function($rootScope, $scope, $state) {
So now, it is working, and let's discuss
I use a parameter in my url
I resolve different data on the state change for each tab (removing this does nothing).
I am not using ui-bootstrap for the tabs but am triggering a $state.go on ng-click of the tab.
Quick answers:
parameter in url exists, e.g. #/parent/tab1?main_id=8000
resolve is trigerred for each controller if controller is reinstantiated. That happens when we navigate to that state (among tabs)
no need to use $state.go, I used:
a snippet:
<a ui-sref="parent.tab1({main_id:'00008'})"> go to tab1 with main_id '00008'</a><br />
<a ui-sref="parent.tab2({main_id:'00008'})"> go to tab2 with main_id '00008'</a><br />
<a ui-sref="parent.tab3({main_id:'00008'})"> go to tab3 with main_id '00008'</a><br />
Check it here
I have an Angular SPA that presents a variety of recommendation lists, and a Google Map of locations, based on different cuts of some restaurant data (see m.amsterdamfoodie.nl). I want each of these lists to have their own URL. In order for Google to crawl the different lists I use <a> tags for the offcanvas navigation.
At present the <a> tag causes a view refresh, which is very noticeable with the map.
I can prevent this using ng-click and $event.preventDefault() (see code snippets below), but then I need to implement a means of updating the browser URL.
But in trying Angular's $state or the browser's history.pushstate, I end up triggering state changes and the view refresh...!
My question is therefore how can I update a model and the URL, but without refreshing the view? (See also Angular/UI-Router - How Can I Update The URL Without Refreshing Everything?)
I have experimented with a lot of approaches and currently have this html
Budget
In the controller:
this.action = ($event) ->
$event.preventDefault()
params = $event.target.href.match(/criteria\/(.*)\/(.*)$/)
# seems to cause a view refresh
# history.pushState({}, "page 2", "criteria/"+params[1]+"/"+params[2]);
# seems to cause a view refresh
# $state.transitionTo 'criteria', {criteria:params[1], q:params[2]}, {inherit:false}
updateModel(...)
And, what is I think is happening is that I am triggering the $stateProvider code:
angular.module 'afmnewApp'
.config ($stateProvider) ->
$stateProvider
.state 'main',
url: '/'
templateUrl: 'app/main/main.html'
controller: 'MainCtrl'
controllerAs: 'main'
.state 'criteria',
url: '/criteria/:criteria/:q'
templateUrl: 'app/main/main.html'
controller: 'MainCtrl'
controllerAs: 'main'
One possible clue is that with the code below if I load e.g. http://afmnew.herokuapp.com/criteria/cuisine/italian then the view refreshes as you navigate, whereas if I load http://afmnew.herokuapp.com/ there are no refreshes, but no URL updates instead. I don't understand why that is happening at all.
This is an example of the way to go if I understand correctly:
$state.go('my.state', {id:data.id}, {notify:false, reload:false});
//And to remove the id from the url:
$state.go('my.state', {id:undefined}, {notify:false, reload:false});
From user l-liava-l in the issue https://github.com/angular-ui/ui-router/issues/64
You can check the $state API here: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
Based on our previous discussions, I want to give you some idea, how to use UI-Router here. I believe, I understand your challenge properly... There is a working example. If this not fully suites, please take it as some inspiration
DISCLAIMER: With a plunker, I was not able to achieve this: http://m.amsterdamfoodie.nl/, but the principle should be in that example similar
So, there is a state definition (we have only two states)
$stateProvider
.state('main', {
url: '/',
views: {
'#' : {
templateUrl: 'tpl.layout.html',
controller: 'MainCtrl',
},
'right#main' : { templateUrl: 'tpl.right.html',},
'map#main' : {
templateUrl: 'tpl.map.html',
controller: 'MapCtrl',
},
'list#main' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
},
},
})
.state('main.criteria', {
url: '^/criteria/:criteria/:value',
views: {
'map' : {
templateUrl: 'tpl.map.html',
controller: 'MapCtrl',
},
'list' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
},
},
})
}];
This would be our main tpl.layout.html
<div>
<section class="main">
<section class="map">
<div ui-view="map"></div>
</section>
<section class="list">
<div ui-view="list"></div>
</section>
</section>
<section class="right">
<div ui-view="right"></div>
</section>
</div>
As we can see, the main state does target these nested views of the main state: 'viewName#main', e.g. 'right#main'
Also the subview, main.criteria does inject into layout views.
Its url starts with a sign ^ (url : '^/criteria/:criteria/:value'), which allows to have / slash for main and not doubled slash for child
And also there are controllers, they are here a bit naive, but they should show, that on the background could be real data load (based on criteria).
The most important stuff here is, that the PARENT MainCtrl creates the $scope.Model = {}. This property will be (thanks to inheritance) shared among parent and children. That's why this all will work:
app.controller('MainCtrl', function($scope)
{
$scope.Model = {};
$scope.Model.data = ['Rest1', 'Rest2', 'Rest3', 'Rest4', 'Rest5'];
$scope.Model.randOrd = function (){ return (Math.round(Math.random())-0.5); };
})
.controller('ListCtrl', function($scope, $stateParams)
{
$scope.Model.list = []
$scope.Model.data
.sort( $scope.Model.randOrd )
.forEach(function(i) {$scope.Model.list.push(i + " - " + $stateParams.value || "root")})
$scope.Model.selected = $scope.Model.list[0];
$scope.Model.select = function(index){
$scope.Model.selected = $scope.Model.list[index];
}
})
This should get some idea how we can use the features provided for us by UI-Router:
Absolute Routes (^)
Scope Inheritance by View Hierarchy Only
View Names - Relative vs. Absolute Names
Check the above extract here, in the working example
Extend: new plunker here
If we do not want to have map view to be recreated, we can just omit that form the child state def:
.state('main.criteria', {
url: '^/criteria/:criteria/:value',
views: {
// 'map' : {
// templateUrl: 'tpl.map.html',
// controller: 'MapCtrl',
//},
'list' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
},
},
})
Now our map VIEW will be just recieving changes in the model (could be watched) but view and controller won't be rerendered
ALSO, there is another plunker http://plnkr.co/edit/y0GzHv?p=preview which uses the controllerAs
.state('main', {
url: '/',
views: {
'#' : {
templateUrl: 'tpl.layout.html',
controller: 'MainCtrl',
controllerAs: 'main', // here
},
...
},
})
.state('main.criteria', {
url: '^/criteria/:criteria/:value',
views: {
'list' : {
templateUrl: 'tpl.list.html',
controller: 'ListCtrl',
controllerAs: 'list', // here
},
},
})
and that could be used like this:
<h4>{{main.hello()}}</h4>
<h4>{{list.hello()}}</h4>
The last plunker is here
you can use scope inheritance to update url without refreshing view
$stateProvider
.state('itemList', {
url: '/itemlist',
templateUrl: 'Scripts/app/item/ItemListTemplate.html',
controller: 'ItemListController as itemList'
//abstract: true //abstract maybe?
}).state('itemList.itemDetail', {
url: '/:itemName/:itemID',
templateUrl: 'Scripts/app/item/ItemDetailTemplate.html',
controller: 'ItemDetailController as itemDetail',
resolve: {
'CurrentItemID': ['$stateParams',function ($stateParams) {
return $stateParams['itemID'];
}]
}
})
if child view is inside parent view both controllers share same scope.
so you can place a dummy (or neccessary) ui-view inside parent view which will be populated by child view.
and insert a
$scope.loadChildData = function(itemID){..blabla..};
function in parent controller which will be called by child controller on controller load. so when a user clicks
<a ui-sref="childState({itemID: 12})">bla</a>
only child controller and child view will be refreshed. then you can call parent scope function with necessary parameters.
The short answer ended up being do not put the map inside a view that changes. The accepted answer provides a lot more detail on how to structure a page with sub-views, but the key point is not to make the map part of the view but to connect its behaviour to a view that does change and to use a Controller to update the market icons.
I'm trying to load a template file using a rootscope value as for it's name.
I have a init controller which sets the $rootScope.template to "whatever.html", then I have my route like this:
$stateProvider.state('/', {
url: '/',
access: 'public',
views: {
page: {
controller: 'HomeCtrl',
templateProvider: function($templateFactory, $rootScope) {
return $templateFactory.fromUrl('/templates/' + $rootScope.template);
}
}
}
});
But this doesn't work. It actually freezes the whole chrome so that I have to kill the process in order to stop it... I've also tried this with templateUrl but with no results.
So how could I use my dynamic template file with UI-router?
Similiar to your other question (in order I found them): Angular and UI-Router, how to set a dynamic templateUrl, I also created a working plunker to show how to. How it would work?
So, if this would be state call:
#/parent/child/1
#/parent/child/2
And these would be states:
$stateProvider
.state('parent', {
url: '/parent',
//abstract: true,
templateUrl: 'views.parentview.html',
controller: function($scope) {},
});
$stateProvider
.state('parent.child', {
url: '/child/:someSwitch',
views: {
// see more below
Then we can use this templateProvider definiton:
templateProvider: function($http, $stateParams, GetName) {
// async service to get template name from DB
return GetName
.get($stateParams.someSwitch)
// now we have a name
.then(function(obj){
return $http
// let's ask for a template
.get(obj.templateName)
.then(function(tpl){
// haleluja... return template
return tpl.data;
});
})
},
What we can see is chaining of async results:
// first return of promise
return asyncstuff
.then(function(x){
// second return of a promise once done first
return asyncstuff
.then(function(y){
// again
return asyncstuff
.then(function(z){
return ... it
}
}
}
And that's what the magical templateProvider can do for us... wait until all promises are resolved and continue execution with known template name and even its content. Check the example here. More about template provider: Angular UI Router: decide child state template on the basis of parent resolved object
I have two services - one to store user details and the other to make a call to retrieve those details:
userService stores user details to be used across the entire app (i.e. injected in controllers, services, etc.)
function userService($log) {
var id = '';
var username = '';
var isAuthenticated = false;
var service = {
id: id,
username: username,
isAuthenticated: isAuthenticated
};
return service;
}
authService is used (hopefully just once) to retrieve the user details from a Web API controller:
function authService($log, $http, userService) {
$log.info(serviceId + ': Inside authService method');
var service = {
getUserDetails: getUserDetails
};
return service;
function getUserDetails() {
$log.info(serviceId + ': Inside getUserDetails method');
return $http.get('api/authentication', { cache: true });
}
}
Initially, I had the call to the authService fire in a .run block like so:
.run(['$log', 'authService', 'userService', function ($log, authService, userService) {
authService.getUserDetails()
.then(querySucceeded);
function querySucceeded(result) {
userService.id = result.data.Id;
userService.username = result.data.username;
}
}]);
But the problem was that the getUserDetails-returned promise did not resolve until after I my controllers fired and, thus, too late for me. The user data was not ready.
I then looked at the resolve option in the $stateProvider (for UI-Router):
.state('dashboard', {
url: '/dashboard',
views: {
header: {
templateUrl: 'app/partials/dashboard/header.template.html',
controller: 'DashboardHeaderController',
controllerAs: 'dashboardHeaderVM',
resolve: {
user: function (authService) {
return authService.getUserDetails();
}
}
}
}
})
The assumption is that the view won't be rendered until the promise in the resolve section is, well, resolved. That seems to work fine.
Here's the (relevant part of the) controller where I use the returned user property:
function DashboardHeaderController($log, user) {
var vm = this;
// Bindable members
vm.firstName = user.data.firstName;
}
However, I have two routes (more to come) and a user can navigate to either one. Do I need to have a resolve property in each state section for the authService? I want to fire the call to authService.getUserDetails just once no matter which route is served and have it available after that for any route, controller, etc.
Is there a better (best practice) way to do this?
Not sure about better or best practice, but here is a plunker with my way.
The point is to move resolve into some parent root state. The one who is ancestor of all states in the application:
$stateProvider
.state('root', {
abstract : true,
// see controller def below
controller : 'RootCtrl',
// this is template, discussed below - very important
template: '<div ui-view></div>',
// resolve used only once, but for available for all child states
resolve: {
user: function (authService) {
return authService.getUserDetails();
}
}
})
This is a root state with resolve. The only state with resolve. Here is an example of its first child (any other would be defined similar way:
$stateProvider
.state('index', {
url: '/',
parent : 'root',
...
This approach will work out of the box. I just would like to mention that if the 'RootCtrl' is defined like this:
.controller('RootCtrl', function($scope,user){
$scope.user = user;
})
we should understand the UI-Router inheritance. See:
Scope Inheritance by View Hierarchy Only
small cite:
Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).
It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states...
More explanation could be found in this Q & A
So, what does it mean?
Our root view can pass the resolved stuff into child state only - if their views are nested.
For example, the $scope.user will be inherited in child states/views/$scopes only if they are nested like this
.state('index', {
url: '/',
parent : 'root',
views: {
'' : { // the root view and its scope is now the ancestor
// so $scope.user is available in every child view
templateUrl: 'layout.html',
controller: 'IndexCtrl'
},
'top#index' : { templateUrl: 'tpl.top.html',},
'left#index' : { templateUrl: 'tpl.left.html',},
'main#index' : { templateUrl: 'tpl.main.html',},
},
Check it here
If I correctly understand you want that on page load you would have user info before any controller or service request it.
I had similar task in my current project.
To solve the problem I manually requested current user info before app bootstapping & store it in localStorage.
Then after app bootstrapping all controllers/services have accesss to current user info.
TIP: to get user info before app bootstrap you can still use $http service by manually injecting it:
angular.injector(['ng']).get('$http');
Currently our project is using default $routeProvider, and I am using this "hack", to change url without reloading page:
services.service('$locationEx', ['$location', '$route', '$rootScope', function($location, $route, $rootScope) {
$location.skipReload = function () {
var lastRoute = $route.current;
var un = $rootScope.$on('$locationChangeSuccess', function () {
$route.current = lastRoute;
un();
});
return $location;
};
return $location;
}]);
and in controller
$locationEx.skipReload().path("/category/" + $scope.model.id).replace();
I am thinking of replacing routeProvider with ui-router for nesting routes, but cant find this in ui-router.
Is it possible - do the same with angular-ui-router?
Why do I need this?
Let me explain with an example :
Route for creating new category is /category/new
after clicking on SAVE I show success-alert and I want to change route /category/new to /caterogy/23 (23 - is id of new item stored in db)
Simply you can use $state.transitionTo instead of $state.go . $state.go calls $state.transitionTo internally but automatically sets options to { location: true, inherit: true, relative: $state.$current, notify: true } . You can call $state.transitionTo and set notify: false . For example:
$state.go('.detail', {id: newId})
can be replaced by
$state.transitionTo('.detail', {id: newId}, {
location: true,
inherit: true,
relative: $state.$current,
notify: false
})
Edit: As suggested by fracz it can simply be:
$state.go('.detail', {id: newId}, {notify: false})
Ok, solved :)
Angular UI Router has this new method, $urlRouterProvider.deferIntercept()
https://github.com/angular-ui/ui-router/issues/64
basically it comes down to this:
angular.module('myApp', [ui.router])
.config(['$urlRouterProvider', function ($urlRouterProvider) {
$urlRouterProvider.deferIntercept();
}])
// then define the interception
.run(['$rootScope', '$urlRouter', '$location', '$state', function ($rootScope, $urlRouter, $location, $state) {
$rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {
// Prevent $urlRouter's default handler from firing
e.preventDefault();
/**
* provide conditions on when to
* sync change in $location.path() with state reload.
* I use $location and $state as examples, but
* You can do any logic
* before syncing OR stop syncing all together.
*/
if ($state.current.name !== 'main.exampleState' || newUrl === 'http://some.url' || oldUrl !=='https://another.url') {
// your stuff
$urlRouter.sync();
} else {
// don't sync
}
});
// Configures $urlRouter's listener *after* your custom listener
$urlRouter.listen();
}]);
I think this method is currently only included in the master version of angular ui router, the one with optional parameters (which are nice too, btw). It needs to be cloned and built from source with
grunt build
The docs are accessible from the source as well, through
grunt ngdocs
(they get built into the /site directory) // more info in README.MD
There seems to be another way to do this, by dynamic parameters (which I haven't used).
Many credits to nateabele.
As a sidenote, here are optional parameters in Angular UI Router's $stateProvider, which I used in combination with the above:
angular.module('myApp').config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('main.doorsList', {
url: 'doors',
controller: DoorsListCtrl,
resolve: DoorsListCtrl.resolve,
templateUrl: '/modules/doors/doors-list.html'
})
.state('main.doorsSingle', {
url: 'doors/:doorsSingle/:doorsDetail',
params: {
// as of today, it was unclear how to define a required parameter (more below)
doorsSingle: {value: null},
doorsDetail: {value: null}
},
controller: DoorsSingleCtrl,
resolve: DoorsSingleCtrl.resolve,
templateUrl: '/modules/doors/doors-single.html'
});
}]);
what that does is it allows to resolve a state, even if one of the params is missing.
SEO is one purpose, readability another.
In the example above, I wanted doorsSingle to be a required parameter. It is not clear how to define those. It works ok with multiple optional parameters though, so not really a problem. The discussion is here https://github.com/angular-ui/ui-router/pull/1032#issuecomment-49196090
After spending a lot of time with this issue, Here is what I got working
$state.go('stateName',params,{
// prevent the events onStart and onSuccess from firing
notify:false,
// prevent reload of the current state
reload:false,
// replace the last record when changing the params so you don't hit the back button and get old params
location:'replace',
// inherit the current params on the url
inherit:true
});
Calling
$state.go($state.current, {myParam: newValue}, {notify: false});
will still reload the controller, meaning you will lose state data.
To avoid it, simply declare the parameter as dynamic:
$stateProvider.state({
name: 'myState',
url: '/my_state?myParam',
params: {
myParam: {
dynamic: true, // <----------
}
},
...
});
Then you don't even need the notify, just calling
$state.go($state.current, {myParam: newValue})
suffices. Neato!
From the documentation:
When dynamic is true, changes to the parameter value will
not cause the state to be entered/exited. The resolves will not be
re-fetched, nor will views be reloaded.
This can be useful to build
UI where the component updates itself when the param values change.
This setup solved following issues for me:
The training controller is not called twice when updating the url from .../ to .../123
The training controller is not getting invoked again when navigating to another state
State configuration
state('training', {
abstract: true,
url: '/training',
templateUrl: 'partials/training.html',
controller: 'TrainingController'
}).
state('training.edit', {
url: '/:trainingId'
}).
state('training.new', {
url: '/{trainingId}',
// Optional Parameter
params: {
trainingId: null
}
})
Invoking the states (from any other controller)
$scope.editTraining = function (training) {
$state.go('training.edit', { trainingId: training.id });
};
$scope.newTraining = function () {
$state.go('training.new', { });
};
Training Controller
var newTraining;
if (!!!$state.params.trainingId) {
// new
newTraining = // create new training ...
// Update the URL without reloading the controller
$state.go('training.edit',
{
trainingId : newTraining.id
},
{
location: 'replace', // update url and replace
inherit: false,
notify: false
});
} else {
// edit
// load existing training ...
}
If you need only change url but prevent change state:
Change location with (add .replace if you want to replace in history):
this.$location.path([Your path]).replace();
Prevent redirect to your state:
$transitions.onBefore({}, function($transition$) {
if ($transition$.$to().name === '[state name]') {
return false;
}
});
i did this but long ago in version: v0.2.10 of UI-router like something like this::
$stateProvider
.state(
'home', {
url: '/home',
views: {
'': {
templateUrl: Url.resolveTemplateUrl('shared/partial/main.html'),
controller: 'mainCtrl'
},
}
})
.state('home.login', {
url: '/login',
templateUrl: Url.resolveTemplateUrl('authentication/partial/login.html'),
controller: 'authenticationCtrl'
})
.state('home.logout', {
url: '/logout/:state',
controller: 'authenticationCtrl'
})
.state('home.reservationChart', {
url: '/reservations/?vw',
views: {
'': {
templateUrl: Url.resolveTemplateUrl('reservationChart/partial/reservationChartContainer.html'),
controller: 'reservationChartCtrl',
reloadOnSearch: false
},
'viewVoucher#home.reservationChart': {
templateUrl: Url.resolveTemplateUrl('voucher/partial/viewVoucherContainer.html'),
controller: 'viewVoucherCtrl',
reloadOnSearch: false
},
'addEditVoucher#home.reservationChart': {
templateUrl: Url.resolveTemplateUrl('voucher/partial/voucherContainer.html'),
controller: 'voucherCtrl',
reloadOnSearch: false
}
},
reloadOnSearch: false
})
Try something like this
$state.go($state.$current.name, {... $state.params, 'key': newValue}, {notify: false})
In Angular 2, the accepted answer from RezKesh translates to the following:
this.uiRouter.stateService.go(
"home.myRouteState",
{
"param1": this.myParam1,
"param2": this.myParam2
},
{ notify: false }
);
Assuming you have injected UIRouter into your component's constructor as follows:
constructor(
private uiRouter: UIRouter
) { }
I don't think you need ui-router at all for this. The documentation available for the $location service says in the first paragraph, "...changes to $location are reflected into the browser address bar." It continues on later to say, "What does it not do? It does not cause a full page reload when the browser URL is changed."
So, with that in mind, why not simply change the $location.path (as the method is both a getter and setter) with something like the following:
var newPath = IdFromService;
$location.path(newPath);
The documentation notes that the path should always begin with a forward slash, but this will add it if it's missing.