Refresh a state without refreshing its master view in Angular - javascript

How can I refresh the 'detail' state without refreshing its parent (item).
in routes:
$stateProvider.state('item.detail', {
url: '/:id/detail',
abstract: true,
resolve: {
$modal: ['$modal', function ($modal) {
return $modal;
}]
},
onEnter: ['$state', '$modal', function ($state, $modal) {
$modal
.open({
templateUrl: 'detail.html',
backdrop: 'static'
})
.result.then(function () {
$state.transitionTo('item.detail', {id: $state.params.id}, {reload: true});
})
;
}]
})
This refreshes the item and detail together.
Adding the state the to reload also doesn't work.
Any idea what I'm doing wrong?

Is this what you want to do, I think the interesting part if the reload argument (that you are using):
If reload is a string (or state object), the state object is fetched
(by name, or object reference); and \ the transition reloads the
resolves and views for that matched state, and all its children
states.

Related

Angular ui-router resolve inheritance

I would like to create an abstract parent state, that has only one job: to resolve the current user through an ajax server call, and then pass this object to the child state. The problem is that the child state never gets loaded. Please have a look at this plunker: Example
a state
angular.module('test', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider){
// Parent route
$stateProvider.state('main', {
abstract:true,
resolve: {
user: function(UserService){
return UserService.getUser();
}
}
});
// Child route
$stateProvider.state('home', {
parent: 'main',
url: '/',
controller: 'HomeController',
controllerAs: '$ctrl',
template: '<h1>{{$ctrl.user.name}}</h1>'
});
$urlRouterProvider.otherwise('/');
});
a factory
angular.module('test').factory('UserService', function($q){
function getUser() {
var deferred = $q.defer();
// Immediately resolve it
deferred.resolve({
name: 'Anonymous'
});
return deferred.promise;
}
return {
getUser: getUser
};
});
a controller
angular.module('test').controller('HomeController', function(user){
this.user = user;
});
In this example, the home state will never display the template, I don't really understand why. If I remove the parent: 'main' line, then it displays the template, but of course I get an error because it cannot find the user dependency in the HomeController.
What am I missing? I did everything like it is described in ui-router's documentation, I think this should work.
Every parent must have a target ui-view in template for its child
$stateProvider.state('main', {
abstract:true,
resolve: {
user: function(UserService){
return UserService.getUser();
}
}
template: '<div ui-view=""></div>'
});
NOTE: Another option is to use absolute names and target index.html .. but in this case the above is the way to go (Angularjs ui-router not reaching child controller)

Call a function before refreshing the page

When the user hit F5 or refresh button I need to call a function before refreshing the page, I tried the below code and it did'nt work, please suggest me what I'm doing wrong and is there a better way to do this.
I'm using Anuglar 1.5 with ui-router.
angular.module('module.name', [
]).controller('someController',['$scope', function($scope) {
$scope.$on("$stateChangeStart", function () {
functionToCallOnPageRefresh();
});
}]);
functionToCallOnPageRefresh() is not getting called on page refresh.
you need to create a parent state like as 'secure' and inherit every state in your application with that state like as-
angular.module('moduleName').config(['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
$stateProvider.
state('secure', {
url: "/",
abstract: true,
templateUrl: "/path/to your/ master page",
resolve: {
factory: 'CheckRouting'
}
}).
state('dashboard', {
url: 'dashboard',
templateUrl: 'path/to your /template',
parent: 'secure',
});
}
]);
here i have mentioned
resolve: {
factory: 'CheckRouting'
}
in which CheckRouting inside resolve property, is a factory which is going to do some task (check user is login or not) on sate change or press f5.
in 'secure' state use 'resolve' property to execute a function if user press f5 or state change like as-
(function() {
'use strict';
angular.module('moduleName').factory('CheckRouting', ['$rootScope','$timeout' checkRouting]);
function checkRouting($rootScope,$timeout) {
if ( condition) { //user is loged in
return true;
} else {
$timeout(function() {
$state.go('login');
});
return false;
}
}
}());

Redirect to Child after Parent is resolved

I have a parent route which loads a list of objects in the resolve function. After the user selects a item of this list it loads the child route. The child route appends the itemId to the url. Now I would like that the parent automatically "redirects" to the first item of the list and therefore change to the child route.
I tried calling $state.go in the resolve function after the promise was resolved but that started a endless redirect cycle.
Here is my current setup.
$stateProvider.state("parent", {
url: "/parent/:parentId/children",
templateUrl: "parentTempl.html",
controller: "ParentController",
controllerAs: "vm",
resolve: {
ParentLoadingService: function ($stateParams, ResourceService) {
return ResourceService.request.getChildren({ parentId: $stateParams.parentId }).$promise;
}
}
}).state("parent.child", {
url: "/:childId",
templateUrl: "child.html",
controller: "ChildController",
controllerAs: "vm",
resolve: {
ChildLoadingService: function ($stateParams, ParentLoadingService) {
...
}
}
});
thanks

Angular UI-Router passing data between states with go function does not work

I just started learning angularjs and I am using angular-ui-router. I am trying to send data from one state to another using $state.go but I have no success. Here is what I have so far:
I have not included the html intentionally because I assumed it was not needed if it is needed please tell me and I will add it.
I have configured my states as below:
$stateProvider
.state('public', {
abstract: true,
templateUrl: 'App/scripts/main/views/PublicContentParent.html'
})
.state('public.login', {
url: '/login',
templateUrl: 'App/scripts/login/views/login.html',
controller: 'loginCtrl'
})
$stateProvider
.state('private', {
abstract: true,
templateUrl: 'App/scripts/main/views/PrivateContentParent.html'
})
.state('private.visits', {
url: '/visits',
views: {
'main': {
controller: 'visitsListCtrl',
templateUrl: 'App/scripts/visits/views/VisitsList.html'
}
}
});
When my LoginController is invoked it will execute the below code:
loginModule.controller('loginCtrl', ['$state', function ($scope, $state) {
$state.go('private.visits', { name : "Object"});
}]);
When the private.visits page is active, I am trying to print the $stateParams:
visitsModule.controller('visitsListCtrl', ['$stateParams',
function ($stateParams) {
console.log($stateParams);
}]);
As things state $stateParams is an empty object. I expected it to to contain the object I passed in loginCtrl.
EDIT
It seems that if private.visits url has this url format '/visits/:name' and I also add the property params: ["name"] I get access to the object I send from the public.login state.
The side effect is that the parameters are added to the url which is logical.
I tried doing the same thing with a child state with no url, and in this case it seems that I do not have access to the params I passed from public.login.
How do I send data in child states?
What you have to do is to define the name param in the private.visits state like:
$stateProvider
.state('public', {
abstract: true,
templateUrl: 'App/scripts/main/views/PublicContentParent.html'
})
.state('public.login', {
url: '/login',
templateUrl: 'App/scripts/login/views/login.html',
controller: 'loginCtrl'
})
$stateProvider
.state('private', {
abstract: true,
templateUrl: 'App/scripts/main/views/PrivateContentParent.html'
})
.state('private.visits', {
// NOTE!
// Previously, we were only passing params as an array
// now we are sending it as an object. If you
// send this as an array it will throw an error
// stating id.match is not a function, so we updated
// this code. For further explanation please visit this
// url http://stackoverflow.com/a/26204095/1132354
params: {'name': null},
url: '/visits',
views: {
'main': {
controller: 'visitsListCtrl',
templateUrl: 'App/scripts/visits/views/VisitsList.html',
resolve: {
name: ['$stateParams', function($stateParams) {
return $stateParams.name;
}]
}
}
}
});
And then in the controller access to the name:
visitsModule.controller('visitsListCtrl', ['name',
function (name) {
console.log(name);
}]);
Hope it help you!
When you say:
$state.go('private.visits', { name : "Object"});
You're not passing data to the private.visits state, but rather you're setting a parameter to the private.visits state, which doesn't even support parameters as you have not defined parameters for it in the state config. If you want to share data between states use a service, or if your states have a parent-child relationship then the child state will have access to the parent states data. Seeing as how you don't want the data to sow up in your URLs, I would use a service (getters/setters) to achieve this.

Child state controller is never executed

I was trying to wrap my head around ui-router and I've tried to implement the following logic:
if there is no state, go to state /items
when processing /items, retrieve a list of "items" from the server
when "items" are received go to state /items/:item, where "item" is the first in the list of items, returned by the server
in state /items/:item render a list of items with the corresponding "item" being "highlighted" (the highlighting part is not included in my code)
However, the child state's "controller" function is not executed. I bet it's something really obvious.
Here's the js (I also have it on plunkr with the accompanying templates).
angular.module('uiproblem', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/items');
$stateProvider
.state('items', {
url: '/items',
resolve: {
items: function($q, $timeout){
var deferred = $q.defer();
$timeout(function() {
deferred.resolve([5, 3, 6]);
}, 1000);
return deferred.promise;
}
},
controller: function($state, items) {
// We get to this point successfully
console.log(items);
if (items.length) {
// Attempt to transfer to child state
return $state.go('items.current', {id: items[0]});
}
}
})
.state('items.current', {
url: '/:id',
templateUrl: 'item.html',
controller: function($scope, items) {
// This is never reached, but the I can see the partial being
// loaded.
console.log(items);
// I expect "items" to reflect to value, to which the "items"
// promise resolved during processing of parent state.
$scope.items = items;
}
});
}]);
Plunk: http://plnkr.co/edit/K2uiRKFqe2u5kbtTKTOH
Add this to your items state:
template: "<ui-view></ui-view>",
States in UI-Router are hierarchical, and so are their views. As items.current is a child of items, so is it's template. Therefore, the child template expects to have a parent ui-view to load into.
If you prefer to have the child view replace the parent view, change the config for items.current to the following:
{
url: '/:id',
views: {
"#": {
templateUrl: 'item.html',
controller: function($scope, items) {
// ...
}
}
}
}

Categories