Как мне заставить всплывающие окна работать с содержимым JSON? (Angular, AngularStrap, JSON)

#json #angularjs #angular-strap

#json #angularjs #angular-strap

Вопрос:

Я ни за что на свете не могу понять, как заставить всплывающие окна angular strap работать с возвращаемым содержимым JSON (атрибуты данных находятся в файле JSON).

Plunkr: http://plnkr.co/edit/jVmHwIwJ0KOKCnX6QjVa?p=preview

Любая информация будет с благодарностью принята. большое спасибо!!

HTML

 <!-- Search -->
<div class="well"> 
  <p>Search the term "content"</p>
  <form role="form">
    <div my-search ng-model="selectedContent" class="form-group clearfix search">
      <input type="text" ng-model="selectedContent" ng-options="query as query.searchQuery for query in searchData" bs-typeahead="bs-typeahead" class="form-control search-field"/>
      <button type="button" class="btn btn-primary search-btn" ng-click="updateModel()"><span class="glyphicon glyphicon-search"></span></button>
    </div>
  </form>
</div>

<!-- Dynamic Content -->
<div class="well">
  <h4>{{clickedContent.contentTitle}}</h4>
  <ul>
    <li ng-repeat="item in clickedContent.headlines" ng-bind-html="item.headline"></li>
  </ul>
</div>
  

JSON

       [
        {
            "contentId": 1,
            "searchQuery": "Content set 1 dummy query vestibulum abcdefghijklmnop",
            "contentTitle": "Pretaining to content set 1",
            "popoverTitle": "Query info",
            "popoverContent": "Interesting info about query",
            "headlines": [
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>1st headline in content set 1</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>2nd headline in content set 1</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>3rd headline in content set 1</a>"
                }
            ]

        },
        {
            "contentId": 2,
            "searchQuery": "Content set 2 dummy query vestibulum abcdefghijklmnop",
            "contentTitle": "Pretaining to content set 2",
            "popoverTitle": "Query info",
            "popoverContent": "Interesting info about query",
            "headlines": [
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>1st headline in content set 2</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>2nd headline in content set 2<a/>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>3rd headline in content set 2</a>"
                }
            ]
        },
        {
            "contentId": 3,
            "searchQuery": "Content set 3 dummy query vestibulum abcdefghijklmnop",
            "contentTitle": "Pretaining to content set 3",
            "popoverTitle": "Query info",
            "popoverContent": "Interesting info about query",
            "headlines": [
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>1st headline in content set 3</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>2nd headline in content set 3</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>3rd headline in content set 3</a>"
                }
            ]
        },
            {
            "contentId": 4,
            "searchQuery": "Content set 4 dummy query vestibulum abcdefghijklmnop",
            "contentTitle": "Pretaining to content set 4",
            "popoverTitle": "Query info",
            "popoverContent": "Interesting info about query",
            "headlines": [
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>1st headline in content set 4</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>2nd headline in content set 4</a>"
                },
                {
                  "headline": "<a href='#' data-placement='bottom', data-trigger='hover' data-title='Headline details' data-content='details about headline' bs-popover>3rd headline in content set 4</a>"
                }
            ]
        }
    ]
  

JS

             var app = angular.module('demoApp', ['ngAnimate', 'ngSanitize', 'mgcrea.ngStrap'])
            .config(function ($typeaheadProvider) {
              angular.extend($typeaheadProvider.defaults, {
                template: 'ngstrapTypeahead.html',
                container: 'body'
              }); 
            });

            app.directive('mySearch', function(){
              return {
                restrict: 'A',
                require: 'ngModel',
                link: function($scope, $element, $attrs, ngModel){
                  ngModel.$render = function(){
                     if (angular.isObject($scope.selectedContent)) {
                       $scope.clickedContent = $scope.selectedContent;
                     }
                  }
                   $scope.updateModel = function() {
                     $scope.clickedContent = $scope.selectedContent;
                  }
                }
              }

            })

            function MainController($scope, $templateCache, $http) {

              $scope.selectedContent = '';

              $http.get('searchData.json').then(function(response){
                $scope.searchData = response.data;
                return $scope.searchData;
              });

            };
  

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

1. Это только я или пример сценария действительно работает? Может быть, вы захотите указать, о каких всплывающих окнах вы говорите … и что еще более важно, где они должны быть.

2. извините! демонстрация сложная. Всплывающие окна должны появляться в заголовках после выполнения поиска. Всплывающие окна в typeahead / autosuggest работают отлично, потому что они не поступают из файла json.

Ответ №1:

Я думаю, это то, что вы хотите. если да, то добро пожаловать 🙂

Рабочий пример

в основном я сделал 2 вещи. Мне не нравится отправлять данные в функцию для unsafe-html, лучший способ — создать фильтр и дату передачи через это .. намного приятнее, поскольку вы можете сделать это встроенным, не отправляя их в функцию. Я назвал этот фильтр «небезопасным» в вашем app.js

 app.filter('unsafe', function($sce) {
    return function(val) {
      return $sce.trustAsHtml(val);
    };
});
  

Второй.. как кто-то упоминал выше в комментариях, только потому, что вы можете «визуализировать», это не означает, что оно было скомпилировано.. итак, вам нужно запустить директиву compile для повторной обработки отображаемого HTML-кода и превратить его в код, о котором мы заботимся. Я назвал эту директиву «compile-template»

 app.directive('compileTemplate', function($compile, $parse){
 return {
link: function(scope, element, attr){
  var parsed = $parse(attr.ngBindHtml);
  function getStringValue() { return (parsed(scope) || '').toString(); }

        //Recompile if the template changes
        scope.$watch(getStringValue, function() {
            $compile(element, null, -9999)(scope);  //The -9999 makes it skip directives so that we do not recompile ourselves
          });
      }         
    }
  });
  

и вы бы написали свой «динамический контент» следующим образом:

     <!-- Dynamic Content -->
<div class="well">
  <h4>{{clickedContent.contentTitle}}</h4>
  <ul>
    <li ng-repeat="item in clickedContent.headlines" ng-bind-html="item.headline | unsafe" compile-template></li>
  </ul>
</div>
  

теперь вы можете увидеть, как работает пример.

пожалуйста, дайте отзыв, если это помогло! Спасибо!!!

Ответ №2:

Проблема, с которой вы сталкиваетесь, заключается в том, что AngularJS, ради безопасности ваших клиентов, автоматически очищает ввод HTML в ng-bind-html атрибуте. Он автоматически удаляет любые потенциально вредоносные атрибуты, такие как события JS, атрибуты с префиксами данных, id атрибут (возможно, для предотвращения конфликтов …) и style .

В документации показано, как обойти эту автоматическую очистку.

По сути:

  1. Добавьте метод с любым именем $scope в свой MainController .
  2. Используется $templateCache.trustAsHtml(<html>) для возврата необработанного HTML.
  3. Вместо этого вызовите эту функцию в ng-bind-html атрибуте, чтобы получить необработанный HTML.

К сожалению, я не очень разбираюсь в AngularJS и не смог заставить его работать в вашем примере. (Я не знаю, как передать более или менее динамическую переменную в функцию, я надеялся ng-bind-html="rawHtml(item.headline)" , что этого будет достаточно, но это не так.)

Удачи!

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

1. Спасибо! Я получил атрибуты данных, которые теперь отображаются в html, но он все равно не будет работать: (возможно, проблема с созданием экземпляра

2. если вы проверите, вы увидите, что атрибуты есть, но сценарий всплывающего окна, похоже, не запущен

3. @MuddyMudSkipper Я полагаю, вам нужно каким-то образом сообщить AngularJS о повторном сканировании части HTML.

4. @MuddyMudSkipper Быстрое обновление: обратитесь к docs.angularjs.org/api/ng/service /$compile , чтобы узнать, как обрабатывать фрагмент кода с помощью AngularJS. Извините, у меня сейчас недостаточно времени, чтобы самому просмотреть документацию.