Search code examples
dotvvm

DotVVM: Auto-update based on timer


We have a dotvvm app that displays real-time data. We would like to have this updated every 5 seconds. It is loaded in the InitializeAsync Method:

 public override async Task PreRender()
    {
        if (!Context.IsPostBack)
            await InitializeAsync();

        await base.PreRender();
    }

This sets UsersTotal which is used in the dotHtml:

<span IncludeInPage="{value: HasUsers}">{{value: UsersTotal}}</span>

We want to refresh this not after the user clicks a button, but automatically. All the binding options appear to base based on some event. Does anybody know of a way to accomplish this within the DotVVM framework? Or is there some official way to implement this with a timer in javascript?

Thank you for your time.


Solution

  • There is no built in timer component, but there are several ways to accomplish this.

    JS directive

    The most over-powered way of accomplishing this is to use the DotVVM 3 @js directive to link a JS file into your page and then trigger a NamedCommand from JS. Full documentation is here: https://www.dotvvm.com/docs/3.0/pages/concepts/client-side-development/js-directive/call-dotvvm-from-js. The Javascript you need is (roughly) this:

    export default context => {
    
        setInterval(function () { context.namedCommands["Refresh"]() }, 5000)
    
        return {
            // declare additional JS commands here
        }
    }
    

    Then use a NamedCommand component in the page with your refresh command:

    <dot:NamedCommand Name="Refresh" Command={command: RefreshData()} />
    

    However, you should prefer to use a staticCommand binding for background jobs.

    @service myUsersService = Full.Name.Of.MyUsersService
    
    <dot:NamedCommand Name="Refresh" Command={staticCommand: UsersTotal = myUsersService.FetchUsersTotal()} />
    

    Hidden button

    While the @js directive is a powerful feature, I'd say that for your use case, it would be simpler add a hidden button with this command and trigger it from JS.

    
    <dot:Button Click={staticCommand: same as above} Visible=false ID="refreshButton" />
    
    <dot:InlineScript>
    
    setInternal(function () { document.getElementById("refreshButton").click() }, 5000)
    
    </dot:InlineScript>
    
    

    HTML meta tag

    Even simpler way is to use the <meta http-equiv="refresh" content="5" >, it will instruct the browser to reload the entire page every 5 sec. Works even without JS, but is only acceptable if you don't mind the page is always refreshing.