Action Button to Reload an Individual Block

I’m looking for a way to be able to refresh a block by clicking on a button. Ideally, it would be great to utilize a top bar action button; however, a custom-code block with a button could also work.

I have various refresh and reload scenarios by calling a whole page refresh but I’d like the ability to call an individual block reload by clicking a refresh button.

Being able to check a table block for new line items would be great without having to refresh the entire page. I’m fairly confident it’s doable since we have the reload code (see below), i’m just not sure how to call it with a button.

<script>
window.addEventListener('submit-form-success-table1', () => {
    window.dispatchEvent(new CustomEvent('reload-block-list6'));
});

window.addEventListener('update-record-success-table1', () => {
    window.dispatchEvent(new CustomEvent('reload-block-list6'));
});

window.addEventListener('delete-record-success-table1', () => {
    window.dispatchEvent(new CustomEvent('reload-block-list6'));
});
</script>`

Can you try this and see if works:

<button id="reloadButton" class="button">Reload</button>

<style>
.button {
    display: inline-block;
    padding: 10px 20px;
    font-size: 20px;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    outline: none;
    color: #fff;
    background-color: #4CAF50;
    border: none;
    border-radius: 15px;
    box-shadow: 0 9px #999;
}

.button:hover {background-color: #3e8e41}

.button:active {
    background-color: #3e8e41;
    box-shadow: 0 5px #666;
    transform: translateY(4px);
}
</style>

<script>
document.getElementById('reloadButton').addEventListener('click', function() {
    window.dispatchEvent(new CustomEvent('reload-block-list6'));
});
</script>

Hi,

Solution with a top bar button:

  1. Add a top bar button in your table block. Label would be “Refresh”. Choose the action “Scroll to” and don’t put anything in it - Blank.
  2. In the page settings => custom code => footer add this script:
<script>
  window.addEventListener('block-loaded-table1', function () {
    const button = document.querySelector('#table1 .MuiButtonBase-root:nth-child(2)');
    
    if (button) {
      button.addEventListener('click', () => {
        window.dispatchEvent(new CustomEvent('reload-block-table1'));
      });
    }
  });
</script>

Few things to consider:

  1. Everywhere you see #table1 => change it by the right # (ID/name) of your table block

  2. window.addEventListener('block-loaded-table1', function () { is important as several Softr team members pointed that it would make everything more efficient while running a script linked to a block (specifically a reload block event)

  3. This line is to consider carefully:

#table1 .MuiButtonBase-root:nth-child(2)

In my example, I placed the refresh button in the second position in top bar buttons (there is one button before it. That’s why I use :nth-child(2). If the refresh button is the first => #table1 .MuiButtonBase-root:nth-child(1)

Here is the example, live: https://test-play.softr.app/reload-table

@acjnas @matthieu_chateau Thank you both, this is huge! My app will be so much cleaner now.

Maybe a “reload block” action button will exist natively someday, but in the meantime this works great.

Can this be used to reset the filters on that same block rather than refreshing?

Yes … and no :grimacing:. I actually used it for this purpose but the results in terms of UX are not perfect.

Yes it will refresh the filters (so all the records will appear as if there were no filters).

But the filter names will appear as if nothing changed. Which is very tricky for the users to understand that the filters are actually refreshed.

So I don’t recommend to do this. Feel free to try it to check it yourself

Ah understood, not ideal for my use case but good to know!

In case selector ‘nth-child’ becomes too crowded or stops working, you can target your button by its inner text:

Here we assume that we have a table block named ‘table1’ and a button named ‘↻Refrescar’ that upon click, will refresh table1 block.

<!-- Custom code button to refresh block on click. Targeted by inner text -->
<script>
window.addEventListener('block-loaded-table1', function () {
  const buttons = Array.from(document.querySelectorAll('#table1 .MuiButtonBase-root'));

  const refreshButton = buttons.find(button => button.textContent.includes('↻Refrescar')) || null;

  if (refreshButton) {
    refreshButton.setAttribute('aria-label', 'Refresh');
    refreshButton.addEventListener('click', () => {
      window.dispatchEvent(new CustomEvent('reload-block-table1'));
    });
  }
});
</script>

refresh

Works perfectly thanks @acjnas (for coders, you need to replace 3 times the name of your block) :fire:

Hi All - this is great!

Is there any tweaks to the code we could do to refresh a list block without refreshing the whole page? I’m looking to create a swipe-down to refresh, if possible? thanks in advance (data connected to airtable)

Additionally, is there any way to have users view live data?

E.g there are two separate users:

User A - Creates a new record (data connected to airtable) on a list block > user see’s new record displayed on softr (this already works great)

User B - Is viewing the list block (I would like the new record created by user A to show automatically to user B)

@acjnas @matthieu_chateau

Hi Paulo!

Yes there would be a way to refresh a list block without refreshing the whole page. What would the exact use cae (please describe how - ideally - a user would act)

There would be a way for users to see live data.
That being said, I won’t disclose this (0 chance :sweat_smile:) as:

  1. I don’t know if it still works due to recent Softr updates.
  2. It might overload the Softr app pretty quickly.
  3. As a consequence it needs to be extremely well setup.
  4. Some future datasources have this realtime data feature = Supabase for example. It is way better to run such things from the back-end and not from the front-end.

Hi Matthieu!

Think instagram when we pull down the feed page, it refreshes the feed with new posts - is essentially what I’m creating using ‘List with vertical cards and tag’ with the name ‘community-feed’

I currently have a top tool button (1) as an onclick refresh with a loading screen active as the page reloads

however, ideally, I would like the refresh button to be hidden for mobile users and have them swipe down to refresh the page and have the list refresh - not the page

Haha that makes sense no worries! hopefully with the above would be the workaround!

Hi Matthieu! I added the button and the custom code but every time I click the button, it will transfer to my home page instead of staying the current page. BTW, can you help me modify the action from reloading table 1 to reloading the whole page? Here’s my code:

<script>
window.addEventListener('block-loaded-table1', function () {
  const buttons = Array.from(document.querySelectorAll('#table1 .MuiButtonBase-root'));

  const refreshButton = buttons.find(button => button.textContent.includes('Refresh')) || null;

  if (refreshButton) {
    refreshButton.setAttribute('aria-label', 'Refresh');
    refreshButton.addEventListener('click', () => {
      window.dispatchEvent(new CustomEvent('reload-block-table1'));
    });
  }
});
</script>

Hi!

In order to make it work you need to add event.preventDefault and event.stopPropagation on click event before reloading the block or the page.

In short and simplified, the reason is that the default behaviour given by Softr to the button has the priority.

Also if your table is the old table block reload-block-table1 is ok. If it’s the new table block it should be reload-table1. As the selector has .MuiButtonBase-root, I guess this is the old table block.

So, let’s say table1 is the old table block then the script should be:

<script>
window.addEventListener('block-loaded-table1', function () {
  const buttons = Array.from(document.querySelectorAll('#table1 .MuiButtonBase-root'));

  const refreshButton = buttons.find(button => button.textContent.includes('Refresh')) || null;

  if (refreshButton) {
    refreshButton.setAttribute('aria-label', 'Refresh');
    refreshButton.addEventListener('click', (event) => {
      event.preventDefault();
      event.stopPropagation();
      window.dispatchEvent(new CustomEvent('reload-block-table1'));
    });
  }
});
</script>

If you want to reload the full page instead of only the block:

<script>
window.addEventListener('block-loaded-table1', function () {
  const buttons = Array.from(document.querySelectorAll('#table1 .MuiButtonBase-root'));

  const refreshButton = buttons.find(button => button.textContent.includes('Refresh')) || null;

  if (refreshButton) {
    refreshButton.setAttribute('aria-label', 'Refresh');
    refreshButton.addEventListener('click', (event) => {
      event.preventDefault();
      event.stopPropagation();
      window.location.reload();
    });
  }
});
</script>

Thanks for replying! I checked my table block and found it’s actually a new table. So besides modify reload-block-table1 to reload-table1, what else should I change in the code? And I tried the second code you provided, it still return to the home page.

Second line to be changed. Also setAttribute is useless.
Script to be inserted in the custom code header of the page settings.
Also, table1 should be your block ID.

And finally the action you set in the Softr studio for the button “Refresh” should be "open page " and select page => nothing, leave it. It can work if you actually point to a page but it might be faster without selecting a page.

<script>
window.addEventListener('block-loaded-table1', function () {
  const buttons = Array.from(document.querySelectorAll('#table1 a'));

  const refreshButton = buttons.find(button => button.textContent.includes('Refresh')) || null;

  if (refreshButton) {
    refreshButton.addEventListener('click', (event) => {
      event.preventDefault();
      event.stopPropagation();
      window.location.reload();
    });
  }
});
</script>
1 Like

Cooooooool! It works! Thanks Matthieu!

1 Like

Hi Matthieu, when I move to any other pages I can still see the last code made for the certain page in Custom Code. Is it a new update that all pages share the same custom code entry field or just a bug?