Search code examples
javascriptasp.netdotvvm

How do I tell a Javascript method to wait until after binding values to execute in DotVVM?


I use a value binding (<dot:HtmlLiteral Html="{value: BannerHTML}" class="mainBanner"/>) to generate some of my page content based on a number of variables.

I also need to run some javascript on the generated HTML to fix a few minor niggles, like matching font size for unusual scaling scenarios and the like. As standard, I place executable javascript at the end of an HTML document.

Generated HTML in one of these scenarios:

<div class="mainBanner" data-bind="html: BannerHTML">
    <div class="mainBanner-upper">some text</div>
    <div class="mainBanner-face" id="mainTitle">some other text</div>
    <div class="mainBanner-lower">some more text</div>
</div>

JS to operate on that HTML:
(requires https://github.com/adactio/FitText.js)

window.fitText(document.getElementById("mainTitle"));

As far as I can see, the javascript executes before the HTML is generated, and javascript that is executed on the element returns Cannot read property 'xyz' of null. How do I tell it to wait? I tried both binding the javascript file to a resource, and simply writing it in with <script> tags at the end of the body element without success.


Solution

  • As your problem seems to be DOM related, I can propose you two approches.

    1. Your javascript must check and wait for DOM. On which I strongly suggest you to read this answer to ...how to call a function when the page/DOM is ready...

    2. Add your script dynamically after your data is binded (I'm not really sure about this)

    Good luck.

    EDIT

    So I went and took a look to the dotvvm documentation to look for events calls and noticed something interesting :

    Every DotVVM page includes Dotvvm.js which defines dotvvm in the global scope. This object can be used to access viewmodel and react to various page events.

    This allows you to access specifics events fired by DOTVVM, you only have to find the one you need in your case. I provided you with an example below.

    You could try something like this (the event may no be the one you need) :

    <script>
        //By subscribing to the event, your code will only be executed 
        // if "init" event is fired by dotvvvm
        dotvvm.events.init.subscribe(()=>{ 
            window.fitText(document.getElementById("mainTitle"));  
            //basically enclose the content of your script tag with this.
        });
    </script>
    

    Please do read the documentation as I may have omitted something ? DOTVVM Javascript Events