This repository has been archived by the owner on May 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 187
Allow ion-nav-bar to work in modals #217
Open
sinedied
wants to merge
1
commit into
ionic-team:master
Choose a base branch
from
sinedied:feature/modal-nav-bar
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Hi, I've implemented your commit, but when the modal pops up, the view is blank and hidden. Would you know what is wrong? UPDATE - SOLUTION: Turns out |
@osirisr It should work with Here is the generic modal we use for navigation, along with a dedicated service to handle show/hide using navigation events and properly take care of history stuff: modal: <ion-modal-view id="modal-nav-screen" class="modal-nav-screen">
<ion-nav-bar class="bar-positive has-shadow">
<ion-nav-title ng-bind="modalViewTitle"></ion-nav-title>
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view name="modal-nav"></ion-nav-view>
</ion-modal-view> modal-navigation-service.ts /**
* Modal navigation service: manages view navigation inside modals.
*/
export class ModalNavigationService {
static MODAL_NAV_VIEW_TARGET = 'modal-nav@';
static MODAL_SHOWN_EVENT = 'modalNav.shown';
static MODAL_HIDDEN_EVENT = 'modalNav.hidden';
private views: any;
private rootHistory: any;
private backView = null;
private currentView = null;
private modal: ionic.modal.IonicModalController = null;
private options: ionic.modal.IonicModalOptions = {
animation: 'slide-in-up',
focusFirstInput: false,
backdropClickToClose: false,
// Disabled to allow back view navigation
hardwareBackButtonClose: false
};
constructor(private $rootScope: ng.IRootScopeService,
private $ionicModal: ionic.modal.IonicModalService,
private $state: angular.ui.IStateService,
private $ionicHistory: ionic.navigation.IonicHistoryService) {
}
/**
* Initializes modal navigation service.
* Hooks are set up to automatically show/hide the navigation modal with special states targeting the "modal-nav@"
* view.
*/
init(): void {
if (!this.modal) {
// Set up modal with a separate named ion-nav-view
let options: ionic.modal.IonicModalOptions = Util.copy(this.options);
options.scope = this.$rootScope;
this.modal = this.$ionicModal.fromTemplate(<string>require('modal-navigation.modal.html'), options);
// Listen to view change to show/hide modal when needed
this.$rootScope.$on('$stateChangeStart', (event: ng.IAngularEvent,
toState: angular.ui.IState,
toParams: any,
fromState: angular.ui.IState) => {
let fromModal = fromState['views'] && fromState['views'][ModalNavigationService.MODAL_NAV_VIEW_TARGET];
let toModal = toState['views'] && toState['views'][ModalNavigationService.MODAL_NAV_VIEW_TARGET];
if (fromModal && !toModal && this.modal.isShown()) {
// If we are navigating from a modal state to a normal state, cancel event and hide modal
event.preventDefault();
this.hide();
} else if (!fromModal && toModal && !this.modal.isShown()) {
// If we are navigating from a normal state to a modal state, show modal
this.show();
}
});
// If the modal was not hidden with hide() method, properly restore state
this.$rootScope.$on('modal.hidden', (event: ng.IAngularEvent, modal: ionic.modal.IonicModalController) => {
if (modal === this.modal) {
this.hide();
}
});
}
}
/**
* Sets the modal navigation options.
* Must be used before calling the `init()` method.
* @param {IonicModalOptions} options The options to set.
*/
setOptions(options: ionic.modal.IonicModalOptions): void {
angular.extend(this.options, options);
}
/**
* Hides the modal and restore state history properly.
*/
hide(): void {
let currentView = this.currentView;
if (currentView !== null) {
// Restore ionic history properly
(<any>this.$ionicHistory).backView(this.backView);
(<any>this.$ionicHistory).currentView(currentView);
// delete all views created within the modal
let viewHistory = this.$ionicHistory.viewHistory();
_.each(viewHistory.views, (data: any, key: string) => {
if (!this.views[key]) {
delete viewHistory.views[key];
}
});
// all modals are created on the root scope
// reset history for the the 'root' history id
viewHistory.histories.root = this.rootHistory;
this.backView = null;
this.currentView = null;
this.modal.hide();
// bugfix : delete stateParam from stateId for route with id inside url
let stateId = currentView.stateId ? currentView.stateId.split('_').shift() : '';
// Properly restore browser's history in case of back navigation action
this.$state.go(stateId, currentView.stateParams);
this.$rootScope.$broadcast(ModalNavigationService.MODAL_HIDDEN_EVENT);
}
}
/**
* Checks if the current state is shown within a modal.
* @return {boolean} True if the current state is shown within a modal.
*/
isModalState(): boolean {
let views = this.$state.current['views'];
return !!(views && views[ModalNavigationService.MODAL_NAV_VIEW_TARGET]);
}
/**
* Shows the modal.
* This method should not be called directly, it it called when trying to navigate to a state targeting the
* "modal-nav@" view.
*/
private show(): void {
if (!this.modal.isShown()) {
// Save current state to properly restore ionic history when the modal is hidden
this.backView = this.$ionicHistory.backView();
this.currentView = this.$ionicHistory.currentView();
this.views = Util.copy(this.$ionicHistory.viewHistory().views);
this.rootHistory = Util.copy(this.$ionicHistory.viewHistory().histories.root);
this.$ionicHistory.nextViewOptions({ disableAnimate: true });
this.modal.show();
this.$rootScope.$broadcast(ModalNavigationService.MODAL_SHOWN_EVENT);
}
}
} Just call Here's an example route using this: .state('editModal', {
views: {
'modal-nav@': {
template: <string>require('edit.html'),
controller: 'editController as vm'
}
}
}) |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Short description of what this resolves:
This allows using
<ion-nav-bar>
directive properly inside modal, with animations and back button working as expected.Changes proposed in this pull request:
<ion-nav-bar>
is within a modal or not and separate those within and those not when updating.<ion-view>
lifecycle events to be triggered when inside a modal that has a<ion-nav-view
You can now use nested states inside modals, with routes like this one:
Then you can use in a modal this way:
Ionic Version: 1.x
Fixes: #1838, #1893, trello issue, related forum post