How to implement 'In-place' loading? Gif attached

Hello there!

I’m wondering how this Pitnerest-like loader can be implemented in Meteor + React? The point is not to instantly upon user action reload the whole page or section and then showing a spinner, but rather show that spinner in-place where the user took action and reload the page only when it’s ready to render (all data fetched).

This is about app’s structure and behavior, not spinner placement.

Is there a proper name for such UX practice?

I have done this with blaze a few times. I did something like this using peerlibrary:blaze-components

class LoginButton extends BlazeComponent {
  onCreated() {
    this._submitted = new ReactiveField(false);
  }
  get submitted() {
    return this._submitted();
  }
  events() {
    return {
      'click button': e => {
        this._submitted(true);
      }
    }
  }
}

with the template looking like this

template(name="loginButton")
  if submitted
    button(disabled="true")
      +spinner
  else
    button(data-action="login")
      | Log In

There is a Javascript library specially built for that purpose: Ladda.

@corvid, @M4v3R, your suggestions cover the visual side of things, the button. I meant the way an app behaves in general.

For example, a button loads another route, which renders another React component (Blaze template). That component is responsible for fetching data and until it isn’t done it shows a spinner. So this is a usual way of making Meteor application, as this forum itself.
What I’m after is a ‘magic button’, which somehow knows what data a pending route needs and loads that data first (while in-button spinner spins), but actually goes to that route only when it is ready to be fully rendered.

use a combination of reactive variables, blaze helper functions and spacebars if-statements. Should be trivial, but I can share an example if you need. Also, if you want this kind of behaviour across different parts of your app, you could make a reusable component for exactly this.

What I’m after is a ‘magic button’, which somehow knows what data a pending route needs and loads that data first (while in-button spinner spins)

Wait, are you going to a new page or something? I’m not sure I get it. Don’t you just want a callback/promise? For example, on reset password or something:

'submit #reset-password-form': async function (e) => {
  this._loading(true);
  const token = FlowRouter.getParam('token');
  const password = AutoForm.getFieldValue('password');
  try {
    await Promise.denodeify(Accounts.resetPassword).call(Accounts, token, password);
    FlowRouter.go('/some/other/route');
  } finally {
    this._loading(false);
  }
}

So basically, it will show a loading indicator until Accounts.resetPassword has completed

Thank you @corvid for your reply!

Take this forum for instance. There is a list of topics. Once you click on any, you are taken instantly to another route (topic’s page), which is initially blank with a spinning loader. After all subscriptions are ready, the page gets rendered.

Now what I was thinking about is the same list of topics, and once you click on any of those you aren’t taken away from this list the same moment, but a spinner shows up next to clicked list item. Only after ‘preloading’ of requested page is finished you are redirected to that topic’s page, which is instantly ready to be rendered fully without additional loading.

Thanks in advance!

This would be really easy if you used Redux with your React…

You would eventually do the Login in a modal window and blank the background possibly in 2 ways:

  1. a colored absolutely positioned div in between the modal and your content.
  2. your content shifted horizontally to -9999px.

On click the Login button replace the text with a spinner (local state of your login modal).
On success on Meteor login, you start moving things around.
either 1: on page finished painting (or if any correspondent in React) add a display: none to your colored div, hide modal.
or 2. shift your content horizontally to 0 and hide modal.

You would need to pass props (states of different components) up and down on your component tree and this is why it can be so easily done with Redux (or other state management in React).