Handlebars error after migration



  • I'm migrating a report from a self-hosted JsReport server (version 2.6.0) to JsReport Studio.
    During testing all of my scripts appear to run properly from what I can tell from the profiler:

    0_1667311005568_Screenshot 2022-11-01 095618.png

    Here are the error details:

    name.indexOf is not a function
    
    (system-helpers.js line 1570:42)
    
      1568 |
      1569 |   const jsreport = require('jsreport-proxy')
    > 1570 |   const assetVal = await jsreport.assets.read(path, encoding)
           |                                          ^
      1571 |   return assetVal
      1572 | }
      1573 |
    
    TypeError: name.indexOf is not a function
        at readAsset (/app/node_modules/@jsreport/jsreport-assets/lib/assetsShared.js:52:34)
        at Object.read (/app/node_modules/@jsreport/jsreport-assets/lib/worker.js:112:25)
        at Object.asset (system-helpers.js:1570:42)
        at Object.<anonymous> (/app/node_modules/@jsreport/jsreport-core/lib/worker/render/executeEngine.js:311:27)
        at Object.wrapper (/app/node_modules/handlebars/dist/cjs/handlebars/internal/wrapHelper.js:15:19)
        at Object.main (eval at compile (/app/node_modules/@jsreport/jsreport-handlebars/lib/handlebarsEngine.js:35:30), <anonymous>:231:192)
        at main (/app/node_modules/handlebars/dist/cjs/handlebars/runtime.js:208:32)
        at ret (/app/node_modules/handlebars/dist/cjs/handlebars/runtime.js:212:12)
        at Object.execute (/app/node_modules/@jsreport/jsreport-handlebars/lib/handlebarsEngine.js:80:14)
        at Object.execute (/app/node_modules/@jsreport/jsreport-handlebars/lib/worker.js:27:43)
    

    I'm not really sure where to begin troubleshooting this given that the error appears to be how JsReport Studio is handling this portion of the code.
    I'd be thankful for support or even pointing me in the right direction!


  • administrators

    what is the invoice-main template code? perhaps the asset call you are making there is passing wrong type of argument (first argument to asset should be string).



  • Thanks for the quick response!

    Template code below. It's identical to what is running on the version 2.6.0 server without issue.
    I believe the only asset calls that are being made are to a style sheet and an image, but are encoded as such. (Line 3 and 15).
    Also note that we also use {{asset}} to pass a variable from an API call based on an actual physical asset, in case this is now causing some kind of conflict (line 48).

    <html>
    <style>
        {#asset invoice-styles.css @encoding=utf8}
    </style>
    
    <div class="invoice-box-main">   
        
        <table cellpadding="0" cellspacing="0">
            <tr class="top">
                <td colspan="2">
                    <table>
                        <tr>
                            <td class="title">
                                <div class="company-logo-wrapper" >
                                    <img src='{#asset logo.jpg @encoding=dataURI}'/>
                                </div>
                            </td>
                            <td>
                                Work Order #: {{number}}
                                <br> Created: {{now}}
                                <br> Technician: {{technician}}
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
            <tr class="information ">
                <td colspan="2 ">
                    <table class = "addresses">
                        <tr>
                            <td>
                                Our Company<br>
                                123 Main Street<br>
                                Springfield, IL  24680
                            </td>
                            <td>
                                {{buyer.name}}<br>
                                {{buyer.road}}<br>
                                {{buyer.country}}
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
        </table>
    
        <div >
            <p>Machine:  {{asset}}</p>
        </div> 
    </div>
    
        <div class = "invoice-box-container">
            <div class="invoice-box">
                    <table>
                        <tr>
                            <td>Description of Problem</td>
                        </tr>
                        
                        <tr class="para">
                            <td>
                                {{{problem}}}
                            </td>
                        </tr>
                        
                    </table>
                </div>    
        </div>
    
        <div class = "invoice-box-container">
            <div class="invoice-box">
                <table>
                    <tr>
                        <td>Work Performed</td>
                    </tr>
                    
                    <tr class="para">
                        <td>
                            {{{workPerformed}}}
                        </td>
                    </tr>
                    
                </table>
            </div>
        </div>
    
        <div class = "invoice-box-container">
            <div class="invoice-box">
                <table>
                    <tr>
                        <td>General Recommendations</td>
                    </tr>
                    
                    <tr class="para">
                        <td>
                            {{{generalRecommendations}}}
                        </td>
                    </tr>
                    
                </table>
            </div>
        </div>
    
        <div style='page-break-before: always;'></div>
    
    <div class = "invoice-box-container">
        <div class="invoice-box"> 
    
    <br />
    
    
        <table id="recommendedParts">
        </table>    
    
        <br />
    
        <table id="partsUsed">
        </table>    
    
        <br />
        <br />
    
        <table id="rmaParts">
        </table>    
    
        <br />
    
        <table>
            <tr class ="table-header">
                <td colspan="7">Travel Hours</td>
            </tr>    
            <tr class="heading ">
                <td>Monday</td>
                <td>Tuesday</td>
                <td>Wednesday</td>
                <td>Thursday</td>
                <td>Friday</td>
                <td>Saturday</td>
                <td>Sunday</td>
            </tr>
            
            <tr class="dates">
                <td>{{MoDate}}</td>
                <td>{{TuDate}}</td>
                <td>{{WeDate}}</td>
                <td>{{ThDate}}</td>
                <td>{{FrDate}}</td>
                <td>{{SaDate}}</td>
                <td>{{SuDate}}</td>
            </tr>
            
            <tr class="dates">
                {{#if MoTravelHrs}}
                <td>{{MoTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if TuTravelHrs}}
                <td>{{TuTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if WeTravelHrs}}
                <td>{{WeTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if ThTravelHrs}}
                <td>{{ThTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if FrTravelHrs}}
                <td>{{FrTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if SaTravelHrs}}
                <td>{{SaTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if SuTravelHrs}}
                <td>{{SuTravelHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
            </tr>
            
            <tr class="total">
                <td colspan=7>Total Travel Hours:  {{TotalTravelHrs}}</td>
            </tr>
    
        </table>
        
        <br />
        
        <table>
            <tr class ="table-header">
                <td colspan="7">Labor Hours</td>
            </tr>    
            <tr class="heading ">
                <td>Monday</td>
                <td>Tuesday</td>
                <td>Wednesday</td>
                <td>Thursday</td>
                <td>Friday</td>
                <td>Saturday</td>
                <td>Sunday</td>
            </tr>
            
            <tr class="dates">
                <td>{{MoDate}}</td>
                <td>{{TuDate}}</td>
                <td>{{WeDate}}</td>
                <td>{{ThDate}}</td>
                <td>{{FrDate}}</td>
                <td>{{SaDate}}</td>
                <td>{{SuDate}}</td>
            </tr>
            
            <tr class="dates">
                {{#if MoLaborHrs}}
                <td>{{MoLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if TuLaborHrs}}
                <td>{{TuLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if WeLaborHrs}}
                <td>{{WeLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if ThLaborHrs}}
                <td>{{ThLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if FrLaborHrs}}
                <td>{{FrLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if SaLaborHrs}}
                <td>{{SaLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
                {{#if SuLaborHrs}}
                <td>{{SuLaborHrs}}</td>
                {{else}}
                <td>0</td>
                {{/if}}
            </tr>
            
            <tr class="total">
                <td colspan=7>Total Labor Hours:  {{TotalLaborHrs}}</td>
            </tr>
        </table>
    
    <br />
            </div>
        </div>
    </div>    
    
        <div style='page-break-before: always;'></div>
        <div class="invoice-box"> 
        <br />
    
    
            <div class="invoice-box">
                <table id= "images">
    
                </table>
            </div>
    
    
    
    <script>
        //Create Recommended Parts Table
        
        if({{recommendedParts.length}} > 0 ) {
    
            var table = document.getElementById("recommendedParts");
            var header = table.insertRow(-1);
            header.className = "table-header";
            var headerCell = header.insertCell(-1);
            headerCell.setAttribute("colspan","3");
            headerCell.innerHTML = "Recommended Parts";
    
            var columnTitles = table.insertRow(-1);
            columnTitles.className = "heading";
            var partNumber = columnTitles.insertCell(-1)
            var description = columnTitles.insertCell(-1)
            var serialNumber = columnTitles.insertCell(-1)
    
            partNumber.innerHTML = "Part Number";
            description.innerHTML = "Description";
            serialNumber.innerHTML = "Serial Number";
    
    
    
    
            {{#each recommendedParts}}
             var row = table.insertRow(-1);
             row.className = "dates";
             var partNumberCell = row.insertCell(-1);
             var descriptionCell = row.insertCell(-1);
             var serialNumberCell = row.insertCell(-1);
        
    
             partNumberCell.innerHTML = "{{this.partNumber}}";
             descriptionCell.innerHTML = "{{this.description}}";
             serialNumberCell.innerHTML = "{{this.serialNumber}}";
    
             {{/each}}
    
        }
    
    </script>
    
    
    <script>
        //Create Parts Used Table
        
        if({{partsUsed.length}} > 0 ) {
    
            var table = document.getElementById("partsUsed");
            var header = table.insertRow(-1);
            header.className = "table-header";
            var headerCell = header.insertCell(-1);
            headerCell.setAttribute("colspan","3");
            headerCell.innerHTML = "Parts Used During Visit";
    
            var columnTitles = table.insertRow(-1);
            columnTitles.className = "heading";
            var partNumber = columnTitles.insertCell(-1)
            var description = columnTitles.insertCell(-1)
            var serialNumber = columnTitles.insertCell(-1)
    
            partNumber.innerHTML = "Part Number";
            description.innerHTML = "Description";
            serialNumber.innerHTML = "Serial Number";
    
    
    
    
            {{#each partsUsed}}
             var row = table.insertRow(-1);
             row.className = "dates";
             var partNumberCell = row.insertCell(-1);
             var descriptionCell = row.insertCell(-1);
             var serialNumberCell = row.insertCell(-1);
        
    
             partNumberCell.innerHTML = "{{this.partNumber}}";
             descriptionCell.innerHTML = "{{this.description}}";
             serialNumberCell.innerHTML = "{{this.serialNumber}}";
    
             {{/each}}
    
        }
    
    </script>
    
    
    <script>
        //Create RMA Parts Table
        
        if({{rmaParts.length}} > 0 ) {
    
            var table = document.getElementById("rmaParts");
            var header = table.insertRow(-1);
            header.className = "table-header";
            var headerCell = header.insertCell(-1);
            headerCell.setAttribute("colspan","4");
            headerCell.innerHTML = "Parts To Be Returned (RMAs)";
    
            var columnTitles = table.insertRow(-1);
            columnTitles.className = "heading";
            var partNumber = columnTitles.insertCell(-1)
            var description = columnTitles.insertCell(-1)
            var serialNumber = columnTitles.insertCell(-1)
            var rmaNumber = columnTitles.insertCell(-1)
    
            partNumber.innerHTML = "Part Number";
            description.innerHTML = "Description";
            serialNumber.innerHTML = "Serial Number";
            rmaNumber.innerHTML = "RMA Number";
    
    
    
    
            {{#each rmaParts}}
             var row = table.insertRow(-1);
             row.className = "dates";
             var partNumberCell = row.insertCell(-1);
             var descriptionCell = row.insertCell(-1);
             var serialNumberCell = row.insertCell(-1);
             var rmaNumberCell = row.insertCell(-1);
        
    
             partNumberCell.innerHTML = "{{this.partNumber}}";
             descriptionCell.innerHTML = "{{this.description}}";
             serialNumberCell.innerHTML = "{{this.serialNumber}}";
             rmaNumberCell.innerHTML = "{{this.rmaNumber}}";
    
    
             {{/each}}
    
        }
    
    </script>
    
    
    
    <script>
        //Create Images Table
        var createNewRow = true;
        var firstImage = true
        
        {{#each images}}
        
        var i = {{2}}
        
        if(createNewRow){
            var table = document.getElementById("images");
            var row = table.insertRow(-1);
            var cell1 = row.insertCell(-1);
            cell1.innerHTML = "<img src= '{{this}}' /> <p>{{2}}</p> ";
            if(firstImage){
                createNewRow = false;
                firstImage = false
            } 
            
            else if(i % 2 == 0){
                createNewRow = false;
            }
            
            else{
                createNewRow = true;
            }
            
        }
        else{
            
            var rowIndex = Math.ceil(i / 2) - 1;
            var newCell = document.getElementById("images").rows[rowIndex].insertCell(-1);
            newCell.innerHTML = "<img src='{{this}}' /><p>{{2}}</p>";
            createNewRow = true;
        }
        
        {{/each}}
        
        var dataEl = document.getElementById('data-serialized');
        var mainData = JSON.parse(dataEl.innerText);
        document.getElementById("content").innerText = mainData.MoDate
        
    </script>
    
    </html>
    

  • administrators

    hmm i see, since jsreport v3 asset is now a handlebars helper too, so when handlebars see this it thinks your are trying to call the helper, when handlebars find that both data and helper have the same name (asset in this case) it gives more priority to the helper.

    there is easy fix for this, just change your template from {{asset}} to {{./asset}} this will disambiguate the case and will let handlebars know that you want the data.



  • Yep. That was it. Many thanks!


Log in to reply
 

Looks like your connection to jsreport forum was lost, please wait while we try to reconnect.