How to watch for ng-model created with ng-bind-html
Asked Answered
S

2

8

I need some help with an ng-model created with ng-bind-html. I have a JSON file in the server in which I have some html and some inputs like this:

*.json

{  
  "test": {
    "1": {
      "question":"<span>1. something:</span>",
      "options":"<input type='radio' name='q1' ng-model='q.1' value='a'>a) op 1<br><input type='radio' name='q1' ng-model='q.1' value='b'>b) op 2<br><input type='radio' name='q1' ng-model='q.1' value='c'>c) op 3<br><input type='radio' name='q1' ng-model='q.1' value='d'>d) op 4<br><input type='radio' name='q1' ng-model='q.1' value='e'>e) op 5<br>",
      "answer":"c"
    },
    "2": {
        ...
    }
  }
}

Then in my HTML file I have something like:

<div class="testContent">
        <div class="test">
            <div class="questions" ng-repeat="qs in questions" ng-show="questions.length">
                <div ng-bind-html="qs.question"></div>
                <div class="options" ng-bind-html="qs.options">
                </div>
            </div>
        </div>
        <br>
        <div class="nextBtn">
            <a href="#test/6" class="btn btnNext" ng-click="save()"> continue ></a>
        </div>
    </div>

And in my Angular controller I have the ajax call for the JSON file:

controller:

.controller('testCtrl', ['$scope', '$http', 'myService', '$sce', 
function($scope, $http, myService, $sce, ){
    $http.get(urls.url_otis).success(function(data, status){                
            angular.forEach(data.test, function(value, key){                    
                var q = data.test[key];
                q[key] = key;
                q.question = $sce.trustAsHtml(q.question);                    
                q.options = $sce.trustAsHtml(q.options);

                $scope.questions.push(q);
            });
    }).error(function(data, status){console.log(status)});
}

The html is populated but I cannot use $watch for the model (q) generated with this approach.

How can I $watch for changes in the models created in this way?

Thanks in advance...

Spoony answered 3/7, 2014 at 18:5 Comment(4)
You have to create directive which will $compile content of repeated div. Create a plunkr or fiddle and I will create this directive if you don't know how to do it.Maxilliped
Ok. this is the a fiddle of how it should work: jsfiddle.net/carloscarcamo/Dh3Su And this is the code of what I'm trying to do: jsfiddle.net/carloscarcamo/gtV2F In the last one, my model is not working well since I generate the html code with ng-bind-html and the html code is loading from server (from a json file in this case). @Maxilliped I will appreciate your help with the directiveSpoony
there's no difference between this fiddlesMaxilliped
@Maxilliped Sorry for that, this the second one: jsfiddle.net/carloscarcamo/nZ89y/1Spoony
M
16

You have to compile dynamically created elements to let angular know about them.

Directive which can do that may look like this one:

app.directive('compile',function($compile, $timeout){
    return{
        restrict:'A',
        link: function(scope,elem,attrs){
            $timeout(function(){                
                $compile(elem.contents())(scope);    
            });
        }        
    };
});

$timeout is used to run compile function, after ng-bind-html do its job.

Now you can just simply put compile as attribute of div with ng-bind-html:

<div class="questions" ng-repeat="item in questions" ng-show="questions.length" >
   <div ng-bind-html="item.question"></div>
   <div compile class="options" ng-bind-html="item.options"></div>
</div>

Fiddle: http://jsfiddle.net/nZ89y/7/

Maxilliped answered 3/7, 2014 at 21:27 Comment(3)
woooow!!! it looks so simple, it really works, @Maxilliped thank you very much, I will definitely use this directive on my projects :)Spoony
I tried the jsFiddle link. I'm seeing syntax errors in Chrome's javascript console. Did something happen in the last 8 months to break this?Blizzard
@dfoverdx, it seems it was wrong all the time. There was some problems with inputs ng-model. There should be q['1'] instead of q.1. I've also replaced " with '. Updated fiddle: jsfiddle.net/nZ89y/7. Thanks for your comment.Maxilliped
I
0

javascript:

app.controller('demoController', function($rootScope, $scope, $http, $compile){
var arr = [
    '<div>I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em></div>'
    ,'<div>name: <input ng-model="user.name" /></div>'
    ,'<div>age: <input ng-model="user.age" /></div>'];

    $scope.user={};
    $scope.testChange2 = function(){
        var compileFn = $compile( arr[Number.parseInt(Math.random()*10)%3] );
        var $dom = compileFn($scope);
        $('#test').html($dom);
    };
});

html:

<div ng-controller="demoController">
    <button type="button" class="btn w-xs btn-info" ng-click="testChange2();" >test2</button>
    <hr/>
    <div id = "test"></div>
    <hr/>
    <div>user:{{user}}</div>

Intuitivism answered 29/11, 2017 at 8:52 Comment(1)
Although this code may work. but you may need to provide some enough description how does it work to clarify other usersTrichromatism

© 2022 - 2024 — McMap. All rights reserved.