ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.03k stars 13.51k forks source link

ionicView beforeEnter is fired before navElementHtml array is filled #6698

Closed nullquery closed 8 years ago

nullquery commented 8 years ago

Short description of the problem:

The "beforeEnter" function (in ionic.bundle.js) is fired before the "navElementHtml" array is completely filled. The result is that my "ion-nav-buttons" are not visible when the page is reloaded.

What behavior are you expecting?

That "ion-nav-buttons" are processed and then the ionicView beforeEnter function is called, so that when you reload the page the buttons are added to the page.

What happens instead?

When you reload the page or paste a direct URL (parsed by ui-router) in the address bar the "ion-nav-buttons" in my view are not added to the page, because they are added after the "beforeEnter" function is called.

When does the problem NOT occur?

The problem does not occur during normal transitions (i.e., via ui-sref). It does however persist if you try to fix it with $state.go manually.

This appears to be an issue with the lifecycle of the application with "normal" use vs. when the page is reloaded / url is called directly.

From ionic.bundle.js (both modules appear to be coming from ionic.angular.js)


IonicModule
.controller('$ionicView', [
  '$scope',
  '$element',
  '$attrs',
  '$compile',
  '$rootScope',
function($scope, $element, $attrs, $compile, $rootScope) {

[...]

  self.beforeEnter = function(ev, transData) {
    if (transData && !transData.viewNotified) {
      transData.viewNotified = true;

      if (!$rootScope.$$phase) $scope.$digest();
      viewTitle = isDefined($attrs.viewTitle) ? $attrs.viewTitle : $attrs.title;

      var navBarItems = {};

      // at this point navElementHtml does not contain a mapping for 'rightButtons'

      for (var n in navElementHtml) {
        navBarItems[n] = generateNavBarItem(navElementHtml[n]);
      }

      navViewCtrl.beforeEnter(extend(transData, {
        title: viewTitle,
        showBack: !attrTrue('hideBackButton'),
        navBarItems: navBarItems,
        navBarDelegate: navBarDelegateHandle || null,
        showNavBar: !attrTrue('hideNavBar'),
        hasHeaderBar: !!hasViewHeaderBar
      }));

      deregisterFns();
    }
  };

[...]

IonicModule
.directive('ionNavButtons', ['$document', function($document) {
  return {
    require: '^ionNavBar',
    restrict: 'E',
    compile: function(tElement, tAttrs) {
      var side = 'left';

      if (/^primary|secondary|right$/i.test(tAttrs.side || '')) {
        side = tAttrs.side.toLowerCase();
      }

      var spanEle = $document[0].createElement('span');
      spanEle.className = side + '-buttons';
      spanEle.innerHTML = tElement.html();

      var navElementType = side + 'Buttons';

      tElement.attr('class', 'hide');
      tElement.empty();

      return {
        pre: function($scope, $element, $attrs, navBarCtrl) {

          var parentViewCtrl = $element.parent().data('$ionViewController');

// at this point 'side' outputs 'rightButtons', but it's too late to call navElement because beforeEnter has already fired

          if (parentViewCtrl) {
            parentViewCtrl.navElement(navElementType, spanEle.outerHTML);

          } else {
            navBarCtrl.navElement(navElementType, spanEle.outerHTML);
          }

          spanEle = null;
        }
      };
    }
  };
}]);

Other information: (e.g. stacktraces, related issues, suggestions how to fix, stackoverflow links, forum links, etc) From what I can see normally the code from the second snippet is executed first, then "beforeEnter" is executed which adds the navigation elements to the DOM.

When reloading the page or accessing the URL directly the reverse happens. The navigation elements (in my case left button bar and titlebar) are added to the DOM, and after that the 'rightButtons' navigation element is added.

Which Ionic Version? 1.x or 2.x Ionic version 1.3.1

Plunker that shows an example of your issue

N/A at this time, as I'm dealing with proprietary code... I'm actually hoping this is a known issue and has already been resolved / is in the process of being resolved...

Run ionic info from terminal/cmd prompt: (paste output below) Cordova CLI: 6.1.1 Gulp version: CLI version 3.9.1 Gulp local: Ionic CLI Version: 1.7.14 Ionic App Lib Version: 0.7.0 OS: Windows 8.1 Node Version: v5.10.1

msimkunas commented 8 years ago

I believe I'm facing a similar/related issue. Here's a Plunker that illustrates it: http://plnkr.co/edit/haF4l3JlDztFekzdMyBN

The navigation bar cannot be hidden during the beforeEnter. Is this expected behavior? Are there any workarounds?

jgw96 commented 8 years ago

Hello @nullquery would you mind posting a plunker that demonstrates this issue? Thanks for using Ionic!

msimkunas commented 8 years ago

I solved my own problem with the following workaround: http://plnkr.co/edit/haF4l3JlDztFekzdMyBN

I needed to hide the navigation bar upon a certain action and preserve its hidden state across view changes. Setting the hide-nav-bar attribute to a scope variable solves my problem. I'm not sure whether this helps the OP, but I thought like sharing my solution anyway.

jgw96 commented 8 years ago

Thanks for the info @msimkunas ! I am having trouble reproducing this issue, and since the op has not responded to my request for a plunker example I will be closing this issue for now. Thanks for using Ionic!