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
Related
I built web app with angular1 and webpack2.
I want to make modal popup with own state so I used ui.router and
ui.bootstrap.
But the problem is, onEnter method doesn't work.
below is my app.js,
and I brought codes about modal at here :
Open Modal and change URL without change the view in AngularJS
import angular from 'angular';
import 'angular-ui-router';
import 'angular-ui-bootstrap';
import 'angular-resource';
// controllers
import homeController from './pages/home/home-controller';
import playerController from './pages/player/player-controller';
import toolbarController from './components/toolbar-controller';
angular.module('907dg', [
'ui.router',
'ui.bootstrap'
])
.config(($stateProvider, $locationProvider) => {
$stateProvider
.state('home', {
url: '/',
template: require('./pages/home/home.html'),
controller: 'HomeController'
})
// modal codes
.state('player', {
url: '/player/:playerName',
onEnter: function($stateParams, $state, $modal) {
console.log('here is player modal');
$modal.open({
template: '<div><h1>PLAYER MODAL POPUP</h1></div>',
resolve: {},
controller: function($scope, $state) {
$scope.ok = function () {
$scope.$close();
};
$scope.dismiss = function () {
$scope.$dismiss();
};
}
}).result.then(function (result) {
// $scope.$close
}, function (result) {
// $scope.$dismiss
}).finally(function () {
// finally
return $state.transitionTo('home');
});
}
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
})
.controller('MasterController', ($scope) => {
$scope.greeting = 'HERE IS INDEX';
})
.filter('trustAsResourceUrl', ['$sce', function($sce) {
return function(val) {
return $sce.trustAsResourceUrl(val);
};
}]);
playerController();
homeController();
toolbarController();
and the controller that calls modal.
$scope.show = function (pName) {
$state.go('player', { playerName: pName });
};
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);
});
},
}
When I add $uibModalInstance to my controller I get the error:
Unknown provider: $uibModalInstanceProvider <- $uibModalInstance <- EventAdditionalInformationTabCtrl
My controller is defined as:
angular.module('myWebApp.controllers').
controller('EventAdditionalInformationTabCtrl', function ($scope, $uibModalInstance, eventData) {
});
I have another controller that defines the open function:
controller('modalCtrl', function ($scope, $uibModal) {
$scope.open = function (template, instance, size) {
var modalInstance = $uibModal.open({
animation: true,
templateUrl: template,
controller: instance,
size: size
});
};
}).
Then I want to pass the controller that will handle a specific instance of a modal, in this case EventAdditionalInformationTabCtrl.
My app is defined as:
var app = angular.module('myWebApp', [
'myWebApp.services',
'myWebApp.controllers',
'ui.router',
'duScroll',
'ngAnimate',
'ui.bootstrap',
'angularUtils.directives.dirPagination',
'angular-loading-bar'
]);
What am I missing?
EDIT ----
Here's how EventAdditionalInformationTabCtrl is linked to the view in ui-Router.
$stateProvider
.state('event', {
url: '/event',
params: {
eventId: null
},
resolve: {
eventData: ['$http', '$stateParams', function ($http, $stateParams) {
console.log('EventId: ' + $stateParams.eventId);
return $http.get('http://localhost:10569/api/eventView/' + $stateParams.eventId).then(function(response) {
return response.data;
});
}]
},
views: {
'': {
templateUrl: 'partials/events/event.html'
//controller: 'EventCtrl'
},
'eventHeader#event' : {
templateUrl: 'partials/events/event-header.html',
controller: 'EventHeaderCtrl'
},
'eventOverviewTab#event': {
templateUrl: 'partials/events/event-overview-tab.html',
controller: 'EventOverviewTabCtrl'
},
'eventDSOTab#event': {
templateUrl: 'partials/events/event-dso-tab.html',
controller: 'EventDSOTabCtrl'
},
'eventAdditionalInformationTab#event': {
templateUrl: 'partials/events/event-additional-information-tab.html',
controller: 'EventAdditionalInformationTabCtrl'
},
'eventFooter#event': {
templateUrl: 'partials/events/event-footer.html',
controller: 'EventFooterCtrl'
}
}
});
Where you have $uibModalInstance now should just be $uibModal. Use $uibModalInstance when you want to actually create a modal. This plunker is the official example for how to use $uibModal.
You need to inject '$uibModal' into your controller.
Check out the angular ui docs here https://angular-ui.github.io/bootstrap/#/modal
EDIT:
Change this
animation: true,
templateUrl: template,
controller: instance,
size: size
to this
animation: true,
templateUrl: template,
controller: EventAdditionalInformationTabCtrl,
size: size
So I have this routing piece of code:-
$stateProvider.state('app.dashboard', {
url: "/dashboard",
templateUrl: "app/components/dashboard/dashboard.html"
, resolve: {
factory: ["$ocLazyLoad", "$q", ['jquery-sparkline', 'dashboardCtrl'], loadSequence]
},
title: 'Dashboard',
ncyBreadcrumb: {
label: 'Dashboard'
}
And i have this function:-
function loadSequence($ocLL, $q, files) {
}
so basically what i want to do is passing ['jquery-sparkline', 'dashboardCtrl'] to the function loadSequence, these values are simple string values. Is there a way to this.
Maybe i don't understand you
(function () {
'use strict';
angular
.module('plunker')
.config(config);
config.$inject = ['$stateProvider'];
/* #ngInject */
function config($stateProvider) {
$stateProvider
.state('app.dashboard', {
url: '/dashboard',
templateUrl: 'app/components/dashboard/dashboard.html',
controller: 'dashboardCtrl',
controllerAs: 'dashboard',
resolve: {
dashboardService: dashboardService
},
title: 'Dashboard',
ncyBreadcrumb: {
label: 'Dashboard'
}
});
}
dashboardService.$inject = ['$ocLazyLoad', '$q'];
function dashboardService($ocLazyLoad, $q) {
return buttonService.getButtons().then(function (data) {
return data;
});
}
})();
(function () {
'use strict';
angular
.module('app.dashboard')
.controller('dashboardCtrl', dashboardCtrl);
dashboardCtrl.$inject = ['dashboardService','jquery-sparkline'];
function dashboardCtrl(dashboardService,jquery-sparkline) {
var vm = this;
vm.loadSequence = loadSequence;
function loadSequence($ocLL, $q, files) {
}
}
})();
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;
});
}
}
});
}