$uibModal inject resolved item into another resolve - angularjs

i am using $uibModal in a factory, i want to chain the resolves but i am getting a provider error for post.
return {
openTextEditModal: function(id) {
var modalInstance = $uibModal.open({
templateUrl: 'tpl.html',
backdrop: 'static',
controller: function($scope, $uibModalInstance, $sce, post, user, $http, $stateParams) {},
size: 'lg',
resolve: {
post: function() {
return $q.when('testing');
},
user:function(post){
//do stuff with post
return $q.when(userObj);
},
}
});
},
close:function(){
$uibModal.close();
}
};
how can i use a resolved value in the followig resolves? (chaining resolves).

You can't do it like this. However, you can chain promises in one resolve block:
resolve: {
user: function() {
return $q.when('testing')
.then(function(post) {
//do stuff with post
return $q.when(userObj);
});
},
}

Related

scope access when promise resolved in Angular UI-Router

I have a small question regarding scopes and promises.
I declared wiz_ids outside a promise call and I would like to access it again when the promise is resolved.
I tried to use bind() but without luck.
This is my state:
state: 'wizard',
config: {
url: '/wizard',
templateUrl: 'app/partners/wizard/wizard.html',
controller: 'WizardController',
controllerAs: 'vm',
redirectTo: 'wizard.step1',
resolve: {
/* #ngInject */
promiseData: ['$window', '$location', 'WizardDataService', function ($window, $location, WizardDataService) {
var wiz_ids = {
'wiz_install_id': $location.search().install_id,
'wiz_instance_id': $location.search().instance_id
};
return WizardDataService.getWizardData(wiz_ids)
.then(function (response) {
// How do I access wiz_ids from here? //
return response.data;
});
}]
},
}
You could return a more complex object inside then().
Something like:
return WizardDataService.getWizardData(wiz_ids)
.then(function(response) {
var data = {
wiz_ids: wiz_ids,
wiz_data: response.data
}
return data;
});
Then in controller access the individual properties accordingly

Inject Resolve Dependency to Every Controller in UI-Router

I have ui router state like this:
$stateProvider.state('parent', {
templateUrl: 'tpl/a.html',
resolve: {
resA: function() {
return { 'value': 'A' };
}
},
controller: function($scope, resA) {
$scope.resA = resA.value;
}
});
In the template html I use another controller (child controller). This child controller need resolve dependency from ui router state. But, it is not injected to child controller.
tpl/a.html
<h1>Hello</h1>
<div ng-controller="ChildCtrl">
</div>
ChildCtrl
var app = angular.module('app', []);
app.controller('ChildCtrl', function($scope, resA) {
// some codes
});
I got an error, that resA unkonwn in ChildCtrl. How to inject resA in ChildCtrl?
I see 3 options:
1) put the value in $scope of parent controller
//it would be available in child controller in `$scope.a`
$stateProvider.state('parent', {
templateUrl: 'tpl/a.html',
resolve: {
resA: function() {
return { 'value': 'A' };
}
},
controller: function($scope, resA) {
$scope.resA = resA.value;
}
})
.state('parent.child', {
templateUrl: 'tpl/child.html',
controller: function($scope) {
console.log($scope.resA) //'{value: "A"}'
}
});
2) put child controller as controller for a sub-route, and resolve resA there as well
var a = { 'value': 'A' };
$stateProvider.state('parent', {
templateUrl: 'tpl/a.html',
resolve: {
resA: function() {
return a;
}
},
controller: function($scope, resA) {
$scope.resA = resA.value;
}
})
.state('parent.child', {
templateUrl: 'tpl/child.html',
resolve: {
resA: function() {
return a;
}
},
controller: function($scope, resA) {
$scope.resA = resA.value;
}
});
3) make some service that will provide the data (that now is stored in resA) for controller and inject it to both controllers
Checkout #BotanMan's answer.
Also another way, which is similar to the 3. answer.
Put your resource into a service.
var app = angular.module('app');
app.service('resA', function() {
// your service here
});
And include it like so :
$stateProvider.state('parent', {
templateUrl: 'tpl/a.html',
resolve: {
resA: 'resA' //your service name
},
controller: function($scope, resA) {
$scope.resA = resA.value;
}
});
So you can use that resource, like you intended :
var app = angular.module('app', []);
app.controller('ChildCtrl', function($scope, resA) { //now it should work
// some codes
});
See the docs on resolve.

$scope not reflecting data in view, while $rootscope is reflecting?

I am stuck with this from around one week. I am resolving my todo_id on "TodoDetailController", and then using a service to get todo details. But the controller is not working as expected. When I write a simple data on $scope its just not reflecting in my view, but the data in $rootscope is reflecting, But I don't want to use $rootscope everywhere.
Can someone please solve my query?
Here is the github project https://github.com/udayghulaxe/ticitic_todo
This is the project structure
This is what I have done so far
/************* My states config ************************/
.state('dashboard', {
url: '/dashboard',
abstract: true,
views: {
'': { templateUrl: './partials/main.html'},
'header_toolbar#dashboard': { templateUrl: './views/header_toolbar.html' },
'sidenavleft#dashboard': { templateUrl: './views/sidenav.html' },
'widgets#dashboard': { templateUrl: './views/widgets.html'},
'todo_detail#dashboard': { templateUrl: './views/todo_detail.html' }
}
})
.state('dashboard.listdetail', {
url: '/lists/:list_id/',
templateUrl: './partials/list.detail.html',
controller:'ListController',
resolve: {
list_id: function($stateParams){
return $stateParams.list_id;
}
},
data: {
authorizedRoles: [USER_ROLES.user],
pageTitle: 'Lists'
}
})
.state('dashboard.tododetail', {
url: '/lists/:list_id/:todo_id',
templateUrl: './partials/list.detail.html',
controller:'TodoDetailController',
resolve: {
list_id: function($stateParams){
//console.log($stateParams);
return $stateParams.list_id;
},
todo_id: function($stateParams){
//console.log($stateParams);
return $stateParams.todo_id;
}
}
})
/**************** My conrtoller *******************/
app.controller("TodoDetailController",['$rootScope','$scope','$state', '$q', 'UserService', '$window','AuthService','DataService','AUTH_EVENTS','list_id','$mdSidenav','todo_id',
function($rootScope,$scope, $state, $q, UserService, $window, AuthService, DataService,AUTH_EVENTS,list_id,$mdSidenav,todo_id)
{
/********* This data is not relecting at all **********/
$scope.list_id = list_id.toString();
$scope.current_list = UserService.GetTodoBylistid($rootScope.lists, $scope.list_id);
$scope.value = 'Not refelcting in view';
/**************** This is updating in view ***************************/
$rootScope.value2 = 'refelcting in view';
$scope.$watch(todo_id, function() {
$rootScope.todo_id = todo_id;
}, true);
toggleSidenav('right');
};
}]);
Inject $rootscope after $scope like this
app.controller("TodoDetailController",['$scope','$state','$rootScope', '$q', 'UserService', '$window','AuthService','DataService','AUTH_EVENTS','list_id','$mdSidenav','todo_id',
function($scope, $state, $rootScope, $q, UserService, $window, AuthService, DataService,AUTH_EVENTS,list_id,$mdSidenav,todo_id)
]);

templateUrl not rendering when modal opened from iFrame

I have a situation in the application, where I want to load an already available modal, in an iFrame of another application using the same codebase. For this I have used the following code :
new-user-module.js
(function () {
'use strict';
angular
.module('mo.pages.new-user.layouts', ['ui.router', 'ui.bootstrap', 'mo.pages.new-user.services'])
.config(['$stateProvider', newUserRouteConfiguration]);
function newUserRouteConfiguration($stateProvider) {
$stateProvider
.state('new-user', {
url: '/new-user',
onEnter: [
'mo.pages.new-user.services.NewUserPageService', function (newAttachmentPageService) {
newAttachmentPageService.openAttachmentModal();
}
]
});
}})();
new-user-service.js
(function () {
'use strict';
angular
.module('mo.pages.new-user.services')
.service('mo.pages.new-user.services.NewUserPageService', NewUserPageServiceFactory);
NewUserPageServiceFactory.$inject = [
'$stateParams',
'$modal'
];
function NewUserPageServiceFactory($stateParams, $modal) {
var service = {
openUserModal: openUserModal
};
return service;
function openUserModal() {
return function () {
$modal.open({
templateUrl: 'modules/pages/shared/modals/new-user/new-user-modal.html',
controller: 'mo.pages.shared.modals.NewUserModalController as vm',
windowClass: 'new-user-modal',
resolve: {
headerText: function() {
return 'header';
}
},
backdrop: 'static',
size: 'lg'
});
};
}
}})();
The issue, I am facing is that, the modal is loading, when the '/new-user' is getting called in the iFrame, but the templateUrl is not loading.
Check your console, I think you may find an error with your call to newAttachmentPageService.openAttachmentModal();
Since NewUserPageServiceFactory is registered as a service and not really a factory, it should not return anything. You should just be adding the method to the service object, for example:
function NewUserPageServiceFactory($stateParams, $modal) {
this.openUserModal = function() {
return function () {
$modal.open({
templateUrl: 'modules/pages/shared/modals/new-user/new-user-modal.html',
controller: 'mo.pages.shared.modals.NewUserModalController as vm',
windowClass: 'new-user-modal',
resolve: {
headerText: function() {
return 'header';
}
},
backdrop: 'static',
size: 'lg'
});
};
}
}
For a good illustration of the (slight) differences between services and factories see here
Let me know if this works

unable to open a modal with angular and ui.routes

I am trying to follow this example to show a bootstrap modal on a certain state. It works fine without a modal (so the state config should be ok). All needed dependencies (ie angular bootstrap) should be available.
when I do a console.debug($stateParams) before $modal.open I get the correct data, within the $modal.open-method however the stateParams from the last state are returned (the state I am coming from)
Any hints?
EDIT
the relevant state cfg:
.state('publications.view', {
parent: 'publications.productSelection',
url: '/{productSlug:[a-zA-Z0-9-]+}/{docID:[0-9]+}_{slug:[a-zA-Z0-9-]+}',
onEnter: ['restFactory', '$state', '$stateParams', '$modal',
function(restFactory, $state, $stateParams, $modal) {
console.debug($stateParams.docID);
$modal.open({
templateUrl: 'partials/publication.html',
resolve: {
publication: ['restFactory', '$stateParams',
function(restFactory, $stateParams) {
console.debug($state.params);
console.debug($stateParams);
return restFactory.view($stateParams.language, $stateParams.productSlug, $stateParams.docID);
}
]
},
controller: ['$scope', '$sce', 'publication', '$rootScope',
function($scope, $sce, publication, $rootScope) {
$rootScope.pageTitle = publication.data.data.publication.Publication.title;
$scope.publication = $sce.trustAsHtml(publication.data.data.publication.Publication.content);
}
]
});
}
]
});
You can get around this issue by injecting the current $stateParams into the onEnter function, save them as state in some service, and inject that service instead into your modal resolves.
I am adapting the code from here: Using ui-router with Bootstrap-ui modal
.provider('modalState', function($stateProvider) {
var modalState = {
stateParams: {},
};
this.$get = function() {
return modalState;
};
this.state = function(stateName, options) {
var modalInstance;
$stateProvider.state(stateName, {
url: options.url,
onEnter: function($modal, $state, $stateParams) {
modalState.stateParams = $stateParams;
modalInstance = $modal.open(options);
modalInstance.result['finally'](function() {
modalInstance = null;
if ($state.$current.name === stateName) {
$state.go('^');
}
});
},
onExit: function() {
if (modalInstance) {
modalInstance.close();
}
}
});
};
})
Then in your app config section
.config(function($stateProvider, $urlRouterProvider, modalStateProvider) {
modalStateProvider.state('parent.child', {
url: '/{id:[0-9]+}',
templateUrl: 'views/child.html',
controller: 'ChildCtrl',
resolve: {
role: function(Resource, modalState) {
return Resource.get({id: modalState.stateParams.id}).$promise.then(function(data) {
return data;
});
}
}
});
}

Resources