Skip to content

When page is fully rendered event #2403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
OnkelTem opened this issue Nov 30, 2015 · 2 comments
Closed

When page is fully rendered event #2403

OnkelTem opened this issue Nov 30, 2015 · 2 comments

Comments

@OnkelTem
Copy link

How to track the moment when all views are fully rendered?

I need this to set ready attr on <html> element which in its turn is used at server side in a phantomjs script to feed pages back to a search engine bot.

I was trying to use $viewContentLoading/$viewContentLoaded events but given up: they are not paired and are called multiple times in an order which I can't comprehend. The last thing I was hoping on - the second view parameter of $viewContentLoaded, but it's always NULL.

Any ideas?

Related issues: #685 and #2003 . The former seems to be fixing the mess with $viewContentLoading/$viewContentLoaded, but I wonder - is it possible to achieve what I want on 0.2.15

@OnkelTem
Copy link
Author

OnkelTem commented Dec 1, 2015

I'm currently working on this test case:
http://plnkr.co/edit/ED0SGYyJerO1kaNDCwGv?p=preview

Typical output when the app bootstraps:

app is started
script.js:55 renderTrigger's controller is triggered
script.js:42 $viewContentLoaded ...
script.js:51 renderTrigger's post link is triggered
script.js:32 $stateChangeStart:  => home
script.js:36 $stateChangeSuccess:  => home
script.js:63 Controller of 'home' state started
script.js:77 1 (check status attribute on html element)
script.js:77 2 (check status attribute on html element)
script.js:77 3 (check status attribute on html element)
script.js:65 Controller of 'home' state finished
script.js:42 $viewContentLoaded ...
script.js:42 $viewContentLoaded ...

Output when the state is changed:

$stateChangeStart: home => home.page1
script.js:36 $stateChangeSuccess: home => home.page1
script.js:63 Controller of 'home.page1' state started
script.js:77 1 (check status attribute on html element)
script.js:77 2 (check status attribute on html element)
script.js:77 3 (check status attribute on html element)
script.js:65 Controller of 'home.page1' state finished
script.js:42 $viewContentLoaded ...
script.js:42 $viewContentLoaded ...

It seems like I have two ways to achieve what I want:

  1. Using renderTrigger directive on the body, but now it's not triggered after the job is done, instead it's triggered before.

  2. Using $viewContnetLoaded event, but there are bunch of events (for every view), so how to catch the last one?

@OnkelTem
Copy link
Author

OnkelTem commented Dec 2, 2015

Ok, it seems I've finally achieved the initial goal:
http://plnkr.co/edit/ED0SGYyJerO1kaNDCwGv?p=preview

Here is a draft of renderWatcher service which tracks start (of state transition) and end of rendering:

  .service('renderWatcher', function($rootScope) {
    var stack = [];
    var enabled = false;
    this.init = function(startCallback, readyCallback) {
      $rootScope.$on('$viewContentLoading', function(event, view) {
        if (enabled) {
          stack.push(event.targetScope.$id);
        }
      });
      $rootScope.$on('$viewContentLoaded', function(event, view) {
        if (enabled) {
          stack.pop(event.targetScope.$id);
          if (!stack.length) {
            if (readyCallback) {
              readyCallback();
            }
          }
        }
      });  
      $rootScope.$on('$stateChangeStart', function() {
        enabled = false;
        if (startCallback) {
          startCallback();
        }
      });
      $rootScope.$on('$stateChangeSuccess', function() {
        enabled = true;
      });
    }
  })

It can be used like this:

    renderWatcher.init(
      function() {
        console.log('LOADING');
      },
      function() {
        console.log('READY');
      }
    );

Sure instead of stupid printing LOADING and READY texts, you can set status attribute on <html> or if you're using prerender.io this may help:

    renderWatcher.init(
      null,
      function() {
        window.prerenderReady = true;
      }
    );

see https://prerender.io/documentation/best-practices

This requires the patch from: #2003

@OnkelTem OnkelTem closed this as completed Dec 2, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant