Как отслеживать ng-модель, созданную с помощью ng-bind-html

#angularjs #watch #ng-bind-html

#angularjs #Смотреть #ng-bind-html

Вопрос:

Мне нужна некоторая помощь с ng-моделью, созданной с помощью ng-bind-html. У меня есть файл JSON на сервере, в котором у меня есть некоторый html и некоторые входные данные, подобные этому:

*.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": {
        ...
    }
  }
}
  

Затем в моем HTML-файле у меня есть что-то вроде:

 <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>
  

И в моем контроллере Angular у меня есть вызов ajax для файла JSON:

контроллер:

 .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)});
}
  

HTML заполнен, но я не могу использовать $watch для модели (q), созданной с помощью этого подхода.

Как я могу $ отслеживать изменения в моделях, созданных таким образом?

Заранее спасибо…

Комментарии:

1. Вы должны создать директиву, которая будет $compile содержать повторяющийся div. Создайте plunkr или fiddle, и я создам эту директиву, если вы не знаете, как это сделать.

2. ОК. это пример того, как это должно работать: jsfiddle.net/carloscarcamo/Dh3Su И это код того, что я пытаюсь сделать: jsfiddle.net/carloscarcamo/gtV2F В последнем случае моя модель работает некорректно, поскольку я генерирую html-код с помощью ng-bind-html, а html-код загружается с сервера (в данном случае из файла json). @akn Я буду признателен за вашу помощь с директивой

3. между этими скриптами нет разницы

4. @akn Извините за это, это второе: jsfiddle.net/carloscarcamo/nZ89y/1

Ответ №1:

Вы должны скомпилировать динамически создаваемые элементы, чтобы сообщить angular о них.

Директива, которая может это сделать, может выглядеть следующим образом:

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

$timeout используется для запуска функции компиляции после ng-bind-html выполнения ее работы.

Теперь вы можете просто поместить compile в качестве атрибута div с 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>
  

Скрипка:http://jsfiddle.net/nZ89y/7

Комментарии:

1. ого-го!!! это выглядит так просто, это действительно работает, @akn большое вам спасибо, я обязательно буду использовать эту директиву в своих проектах 🙂

2. Я попробовал ссылку jsFiddle. Я вижу синтаксические ошибки в консоли javascript Chrome. Произошло ли что-нибудь за последние 8 месяцев, чтобы нарушить это?

3. @dfoverdx, кажется, это все время было неправильно. Возникли некоторые проблемы с вводом ng-модели. Должно быть q['1'] вместо q.1 . Я также заменил " на ' . Обновленная скрипка: jsfiddle.net/nZ89y/7 . Спасибо за ваш комментарий.

Ответ №2:

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>
  

Комментарии:

1. Хотя этот код может работать. но вам может потребоваться предоставить достаточное описание того, как это работает, чтобы разъяснить другим пользователям