0

Так у меня есть доступ к REST API, что я ударяя, который возвращает следующую предварительно сгенерированный HTML:AngularJS: Компиляция директивы внутри HTML, возвращаемые с помощью API

<p class="p"> 
    <sup id="John.3.16" class="v">16</sup> 
    <span class="wj">“For </span> 
    <span class="wj">God so loved </span> 
    <span class="wj">the world,</span> 
    <span class="wj">that he gave his only Son, that whoever believes in him should not </span> 
    <span class="wj">perish but have eternal life.</span> 
</p> 

Это подарил интересный новый вызов для я в своем изучении AngularJS. Я не могу контролировать HTML, который возвращается из API, так как это не API, который я создал.

Что я пытаюсь сделать (и это может быть совершенно неправильный подход) - это построить директиву класса в классе «v», чтобы я мог добавить атрибут ng-click к номеру стиха и пройти стиховую информацию на другую часть моей заявки.

Ниже приведен код, который у меня есть, который, кажется, ничего не делает, хотя я и думал.

var app = angular.module('ProjectTimothy'); 

app.filter("sanitize", ['$sce', function($sce) { 
    return function(htmlCode){ 
     return $sce.trustAsHtml(htmlCode); 
    } 
}]); 

app.controller("timothy.ctrl.search", ['$scope', '$http', function($scope, $http){ 
    $scope.url = "http://apiendpoint.com/"; 
    $scope.copyright = ""; 

    $scope.search = function() { 
     // Make the request to the API for the verse that was entered 
     // Had to modify some defaults in $http to get post to work with JSON data 
     // but this part is working well now 
     $http.post($scope.url, { "query" : $scope.searchwords, "version": "eng-ESV"}) 
     .success(function(data, status) { 
      // For now I'm just grabbing parts of the object that I know exists 
      $scope.copyright = data.response.search.result.passages[0].copyright; 
      $scope.result = data.response.search.result.passages[0].text; 
     }) 
     .error(function(data, status) { 
      $scope.data = data || "Request failed"; 
      $scope.status = status;   
     }); 

    }; 
}]); 

app.directive("v", ['$compile', function($compile) { 
    return { 
     restrict: 'C', 
     transclude: true, 
     link: function(scope, element, attrs) { 
      element.html("<ng-transclude></ng-transclude>").show(); 
      $compile(element.contents())(scope); 
     }, 
     scope: { id:'@' }, 
     /*template: "<ng-transclude></ng-transclude>",*/ 
     replace: false 
    }; 
}]); 

HTML-шаблон, который заселяется с HTML, возвращенного API:

<div class="bible_verse_search_container" ng-controller="timothy.ctrl.search"> 
    <div class="input-group"> 
     <input type="text" class="form-control" placeholder="Bible Verse To Read (i.e. John 11:35)" ng-model="searchwords"> 
     <span class="input-group-btn"> 
      <button class="btn btn-default" type="button" ng-click="search()">Search</button> 
     </span> 
    </div> 
    <div class="well" ng-show="copyright" ng-bind-html="copyright | sanitize"></div> 
    <div ng-bind-html="result | sanitize"></div> 
</div> 

Так что я надеялся, что произойдет бы, что HTML заполняется в нижней DIV, который связывает HTML, а затем каким-то образом компилируется $ compile, чтобы преобразовать sup v's класса v в директивы, которые я могу изменить. Опять же, я довольно новичок в Angular, поэтому может быть очень простой способ сделать это, как и большинство других вещей в Anguler, которых я еще не нашел.

Действительно, конечная цель состоит в том, что каждый номер стиха преобразуется в собственную собственную директиву, чтобы сделать его доступным для клика и получить доступ к атрибуту id, который он имеет, чтобы я мог отправить эту информацию с каким-то пользовательским контентом обратно мой собственный API.

Это похоже на много информации, поэтому дайте мне знать, если что-то неясно. Я буду работать над этим, поэтому, если сначала понять, я обязательно буду обновлять ответ.

ИДЕТ

Проверенный этот вопрос: https://stackoverflow.com/a/21067137/1507210

Теперь я интересно, если это будет иметь больше смысла, чтобы попытаться преобразовать раздел, где отображается в директиву стих, а затем заставляя контроллер поиска заполнять переменную области видимости с помощью HTML с сервера, а затем использовать это как шаблон для директивы ... думать думать думать

ответ

1

Я думаю, что ваш второй подход - преобразовать se где стих отображается в директиве - было бы хорошим способом сделать это.

Вы можете заменить это:

<div ng-bind-html="result | sanitize"></div> 

с директивой как это:

<verse-display verse-html="{{result}}"></verse-display> 

определение директивы будет выглядеть следующим образом:

app.directive('verseDisplay', ['$compile', function($compile) { 

    function handleClickOnVerse(e) { 
     var verseNumber = e.target.id; 

     // do what you want with the verse number here 
    } 

    return { 
     restrict: 'E', 
     scope: { 
      verseHtml: '@' 
     }, 
     replace: true, 
     transclude: false, 
     template: '<div ng-bind-html="verseHtml | sanitize"></div>', 
     link: function(scope, element, attrs) { 
      $compile(element.contents())(scope); 
      element.on('click', '.v', handleClickOnVerse); 
     } 
    }; 
}]); 

Таким образом, вы могли бы применить свои собственные обработчик кликов к элементу.

Вот fiddle. (Откройте консоль, чтобы увидеть номер стиха, который выйдет из системы.)

1

Возможно, самое неудобное из того, что я разместил здесь, но это довольно классный код. Я не знаю, рекомендую ли я это делать, но вот jsfiddle

Так что одна из причин, почему я называю это неразумной, состоит в том, что введенный код будет запускать любые директивы, которые у вас есть не только по желанию. Могут быть и другие риски безопасности помимо этого. Но это работает фантастически. Если вы доверяете HTML-адресу, который вы извлекаете, то перейдите к нему.

Заканчивать скрипку для остальной части кода:

function unwiseCompile($compile) { 
    return function (scope, element, attrs) { 
     var compileWatch = scope.$watch(
      function (scope) { return scope.$eval(attrs.unwiseCompile); }, 
      function (unwise) { 
      element.html(unwise); 
      $compile(element.contents())(scope); 
      // for better performance, compile once then un-watch 
      if (scope.onlyOnce) { 
       // un-watch 
       compileWatch(); 
      } 
      }); 
    }; 
} 
Смежные вопросы