Dynamic HTML error Onsen 2



  • My app context is generated in the run-time, on onsen 1.3 i was using this function to generate the HTML and compile it,

    $scope.generateFrom = function (div) {
                var el = div;
                var html = HTMLGenerator.getHTML();
                el.innerHTML = html;
                ons.compile(el);
            }
    

    But after upgrading to onsen 2/Angular i am getting this error

    "Error: First argument must be an instance of HTMLElement.
    

    Any suggestions to fix this issue ?



  • @Omar-Hassan Can you post the rest of your JS? Specifically, can you help me understand the HTMLGenerator.


  • Onsen UI

    In Onsen 2.0 you don’t need to compile elements manually. You just need to do document.createElement('ons-page') and you get an ons-page, for example. You can also do document.createElement('div').innerHTML = '<ons-page>...</ons-page>'; if you want to add more attributes or childnodes (:



  • @Fran-Diox
    Can you please provide me with a working example ?
    I have tried your proposed solution but unfortunately it doesn’t work for me.



  • @Omar-Hassan See the below working code for adding list elements to a list:

    var onsItem= document.createElement('ons-list-item');
           onsItem.setAttribute('modifier', "chevron");
           onsItem.setAttribute('onclick', "functionName()");
           onsItem.innerHTML = '<img src="" alt="something here" />';
    document.getElementById('listIDorSomething').appendChild(onsItem);
    

  • Onsen UI

    @Omar-Hassan Exactly as @munsterlander said. I’d only change onsItem.setAttribute('onclick', "functionName()"); with onsItem.onclick = function() {...};.

    You can also create elements using the innerHTML property:

    var dumbDiv = document.createElement('div');
    dumbDiv.innerHTML = '<ons-list><ons-list-item> List with 1 item </ons-list-item></ons-list>';
    var onsList = dumbDiv.firstChild;
    var onsItem = onsList.firstChild;
    


  • @Fran-Diox Is there an advantage for defining the function like that vs referencing another one? Truly curious to see why this is your preference. I am guessing it will have to do with compilation or such / performance advantage. I will probably start doing it this way if that is the case!


  • Onsen UI

    @munsterlander If you set the onclick attribute you are mixing the markup with the code so if you inspect the HTML you will see long lines of JavaScript. Also I guess those functions will be run with eval in the global scope.

    I just Googled it to see what other devs think about this and I found out that it actually has a name: Unobtrusive JavaScript



  • Very interesting read. I would believe this is where you start to see MVC framework implementation taking a stronghold as it would explicitly avoid / separate these issues. Time to do some more best practices reading! :wink:



  • @munsterlander, @Fran Diox

    But all angular directives doesnot work such as ng-click and ng-show,
    Any advise to fix this ?



  • @Omar-Hassan Even using the innerHTML method of adding elements?



  • @munsterlander said:
    Yes, it also does ,not work.
    For example here if you chnaged onlick here to be ng-click

    onsItem.setAttribute('ng-click', "functionName()");
    

    it will not work, all things works well in onsen 1.3.



  • @Omar-Hassan Hmm, interesting. Let me play with this a bit tonight and I will post something back within about 5 hours.


  • Onsen UI

    @Omar-Hassan Oh! Sorry, I didn’t notice you were using AngularJS 1.x. In that case you do need to compile, sorry for the misunderstanding.
    The error says that the div that you get (el variable) is not an HTMLElement. Which element are you passing? The check el instanceof HTMLElement fails.



  • @Fran-Diox
    Here is a sample from my generated HTML,

    <ul class="tabs">
       <li class="current" ng-click="oneClick(0)">ملاحظات</li>
       <li class="current" ng-click="oneClick(1)">عام</li>
    </ul>
    <br>
    <div class="form" ng-show="shouldShow(0)"></div>
    <div class="form" ng-show="shouldShow(1)">
       <p>رصيد أيام الإجازة</p>
       <br><input id="BalanceVactionDays" value="7" name="BalanceVactionDays" type="text" class="text-input" onkeypress="return event.charCode &gt;= 48 &amp;&amp; event.charCode &lt;= 57" ng-init="BalanceVactionDays= 7" ng-model="BalanceVactionDays">
       <div class="error-msgs" ng-messages="requestDetailsFrom.BalanceVactionDays.$error">
          <p ng-message="emptyValidator">Required nn</p>
       </div>
       <p>مدة الإجازة الفعلية \ يوم</p>
       <br><input id="ActualVacationDays" value="1" name="ActualVacationDays" type="text" class="text-input" onkeypress="return event.charCode &gt;= 48 &amp;&amp; event.charCode &lt;= 57" ng-init="ActualVacationDays= 1" ng-model="ActualVacationDays">
       <div class="error-msgs" ng-messages="requestDetailsFrom.ActualVacationDays.$error">
          <p ng-message="emptyValidator">Required nn</p>
       </div>
    </div>
    


  • @Fran-Diox

    If i changed your example to this

     var onsItem = document.createElement('ons-list-item');
                onsItem.setAttribute('modifier', "chevron");
                onsItem.setAttribute('ng-click', 'functionName()');
                onsItem.innerHTML = '<img src="" alt="something here" />';
                ons.compile(onsItem);
    
                var ccc = document.getElementById('listIDorSomething');
                ccc.appendChild(onsItem);
    

    It give me this error

    Error: AngularJS Scope is null. Argument DOM element must be attached in DOM document.
        at Object.ons.compile (angular-onsenui.js:472)
        at Scope.$scope.login_click (app.js:171)
        at angular.js:13924
        at angular-onsenui.js:11397
        at Scope.$eval (angular.js:16052)
        at Scope.$apply (angular.js:16152)
        at ons-button.listener (angular-onsenui.js:11396)
        at defaultHandlerWrapper (angular.js:3346)
        at ons-button.eventHandler (angular.js:3334)(anonymous function) @ angular.js:12520
    17:4400/plugins/cordova-plugin-whitelist/whitelist.js:25 No Content-Security-Policy meta tag found. Please add one when using the cordova-plugin-whitelist plugin.
    


  • I have been working on this, but unfortunately my AngularJS is horrible and haven’t had much success. Hopefully someone else will be able to assist - apologies!



  • @munsterlander

    Thanks for your cooperation,

    Waiting for someone help in this.



  • Dears Onsen ui developers , No fix for this issue ?



  • @Omar-Hassan The Onsen team @Fran-Diox just published an article demonstrating this here: https://onsen.io/blog/auto-style-app-onsen/


  • Onsen UI

    @Omar-Hassan For AngularJS you need to append the element before calling ons.compile. This is explained here: https://onsen.io/guide/overview.html#onscompilefunction

    And I think the error is just that, Argument DOM element must be attached in DOM document. Hope you can fix it with this :)


Log in to reply