Search code examples
javascripthtmlangularjsangularjs-scopeionic-framework

Compiling HTML string template in Angular


I'm converting an online dictionary into a mobile app using the Ionic framework and I'm having some issues. I won't go into too much detail about how the website works, but for its search function, it performs an approximate search on a client-side JSON file and then injects the closest 10 entries to the query into the following HTML template:

"\n<div class='matchContainer'">    <span class=\"matchLeftDiv\">${display_form}<\/span>  \n    <span class=\"matchRightDiv\">${definition}<\/span>  \n    <span style=\"display:block;clear:both;\"> <\/span>\n<\/a><\/div>\n\n\n"

Which is what ends up being displayed in a #results div. In the website there was an anchor element which, when clicked, navigated the user to a more detailed page about the word that they clicked. For the app, I wanted clicking the word to trigger a modal with the same information, so I altered the template by adding ng-click="openModal()" like so:

"\n<div class='matchContainer' ng-click=\"openModal()\">    <span class=\"matchLeftDiv\">${display_form}<\/span>  \n    <span class=\"matchRightDiv\">${definition}<\/span>  \n    <span style=\"display:block;clear:both;\"> <\/span>\n<\/a><\/div>\n\n\n"

But, when the results were inserted into the #results div, ng-click didn't fire. So I had a look here on Stack Overflow, looked over the team treehouse course on Angular as well as the codecademy course and pieced together that I need to compile the HTML and then append it. So I wrote the following function:

$scope.compileHTML = function() {
        var compiledHTML = $compile($("#results"))($scope);
        $("#results").append(compiledHTML);
    };

Then I called it in my function that deals with searching:

$scope.getResult = function(searchWord) {
        if ( $(".input").val() === "") {
            $("#results").hide();
        } else if ( $(".input").attr('id') === "engSearch") {
            dataTyped(searchWord, engSearch);
        } else if ( $(".input").attr('id') === "gitSearch") {
            dataTyped(searchWord, gitSearch);
        } 
        $scope.compileHTML();
    };

And what resulted was very strange. Basically, it only works some of the time. And interestingly, when I did essentially the same thing but with the browse page, it worked! Here's my code for the browse entry compiler.

$scope.compileBrowseHTML = function() {
        var compiledHTML = $compile($("#browseEntries"))($scope);
        $("#browseEntries").append(compiledHTML);
    };

$scope.next10 = function () {
        startIndex += 10;
        tenEntries = get10(entries, startIndex);   
       $("#browseEntries").html(tenEntries.join(""));
        $scope.compileBrowseHTML();
    };

This is my very first post to stack overflow, and I'm a lexicographer who only started coding in August, so please be gentle! And clear! And if there's anything that I can add to make this post clearer, please let me know.

Thanks,

Aidan


Solution

  • You should use ng-repeat and data-binding for this, or filters, not template compiling.

    Your way of doing this task is not the "angular way". You should not manipulate the DOM from a controller.

    Take a look at these links link link2