1

My question may be a little confusing and I will try to make it as simple as possible. I'm trying to scrape a website using cheerio.js, extract just the input fields, send those to my front end, render them and bind them to a value on my controller using ng-model. Angular won't just let me display raw html for security reasons so I'm sending it through $sce.trustAsHtml() and ng-bind-html. My problem arises when I try to bind that input field to a value on the controller using ng-model. It just doesn't work and I don't know if it has something to do with $sce or if my approach is all wrong.

Controller:

app.controller('homeCtrl', function ($scope, $sce, ScraperFactory) {

    $scope.value

    $scope.renderHtml = $sce.trustAsHtml('<input type="text" ng-model="value"/>')

});

HTML:

<section id="home">

    <pre> value = {{value}}</pre>

    <input type="text" ng-model="value" />

    <p ng-bind-html="renderHtml"></p>

</section>

The pre and the first input work as intended.

isherwood
  • 58,414
  • 16
  • 114
  • 157
JN18
  • 97
  • 9
  • the compile service might work here try something like this this $scope.renderHtml = $compile($sce.trustAsHtml('')) – TimCodes Oct 20 '15 at 18:08
  • look here you will find your answer, you need to tell angular to bind your ng-model inside your raw html with a directive using $compile. http://stackoverflow.com/a/24563545/861206 – rbinsztock Oct 20 '15 at 18:25
  • Oh my god that worked. It almost seems magical haha. Thanks! – JN18 Oct 20 '15 at 18:50
  • didnt see the two comments awesome!! – TimCodes Oct 20 '15 at 18:51
  • Okay so it worked when everything was synchronous. But when I added in the part when I'm asynchronously getting the code from the backend, ngmodel no longer works. Again the html displays, but it isn't hooked up to the controller value. Do I need to call a $scope.$digest() or something? – JN18 Oct 20 '15 at 19:05
  • Okay, I figured out how to do it asynchronously: after ajaxing back for the code, broadcast an event into the scope. Then on the compile function add a scope event listener to run the compile again. So call $scope.$broadcast("Render_ready") after the ajax call is complete. This is the render function: scope.$on("Render_ready", function () { $timeout(function () { $compile(elem.contents())(scope) }) }) – JN18 Oct 20 '15 at 19:23

1 Answers1

0

Create a custom directive that takes the html as input then simply append the compiled html to the element. you could do something fancier with transclusion but here is some code and a working plunk.

// js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $sce, $compile) {
  $scope.name = 'World';

  $scope.value;

  $scope.html = '<input  compile type="text" ng-model="value"/>';

});

app.directive("compileHtml", function( $compile) {
    return {
        restrict: "A",

        link: function (scope, element, attributes) {

            element.append($compile(attributes.compileHtml)(scope));

        }
    }
});

// html 

<section id="home">

    <pre> value = {{value}}</pre>

    <input type="text" ng-model="value" />

    <p compile-html ={{html}}></p>

</section>

http://plnkr.co/edit/XSGnyMGNa1vb4dB2z9wH?p=preview

TimCodes
  • 365
  • 2
  • 14