IntroJS Добавить директиву в пошаговую разметку

Я использую introJS для руководства пользователя. Я могу показать различные функции, однако я хочу добавить директиву в разметку, например:

$scope.IntroOptions = {
    steps: [
        {
            element: "#step1",
            intro: "Click the button: <button my-directive>Test Directive</button>",
            position: 'left'
        }
    ],

С приведенным выше я вижу текст «Нажмите кнопку» плюс кнопку по умолчанию.

myDirective.js

var myDirective = function () {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind('click', function() {
                    console.log('you clicked the directive');
                });
            }
        };
    };

return [myDirective];

Однако с учетом вышеизложенного. console.log никогда не отображается, но когда я проверяю разметку, я вижу:

<button my-directive>Test Directive</button>

Если я размещу директиву где-либо еще в своем приложении, console.log будет успешным.


person Oam Psy    schedule 05.05.2016    source источник
comment
Можете ли вы поместить это в Codepen, пожалуйста?   -  person Mike Feltman    schedule 09.05.2016


Ответы (3)


Может быть, это может помочь вам.

Я пытался реализовать решение @S.Klechkovski здесь, но мне это не удалось. Но пусть кто-нибудь поэкспериментирует с этим.

Но на самом деле я сделал то, что вам нужно здесь:

function appCtrl($scope, $compile) {

  function onIntroAfterChange(targetElement, scope) {

    angular.element(document.querySelector(".introjs-tooltiptext"))
      .append($compile(
          angular.element(
            "<button my-directive>Test Directive</button>"))
        (scope)).html()
  }

  $scope.onIntroAfterChange = onIntroAfterChange;

  $scope.IntroOptions = {
    steps: [{
      element: "#step1",
      intro: "Click the button:",
      position: 'bottom'
    }]
  };
}

(подсказка состоит в том, чтобы использовать ng-intro-onAfterChange для компиляции с использованием надлежащей области видимости) Плохая часть заключается в том, что я жестко запрограммировал шаблон там.

Но вы можете пойти дальше и установить шаблон как атрибут элемента, для которого вы хотите показывать всплывающую подсказку. Не имел возможности получить доступ к intro полю шага. Итак... Извините за этот крайний уровень кодирования порнографии здесь (кажется, работает):

Полный JS:

angular.module("app", ["angular-intro"])
  .directive("myDirective", myDirective)
  .controller("appController", appCtrl);

function myDirective() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      element.bind('click', function() {
        console.log('you clicked the directive');
      });
    }
  };
};



function appCtrl($scope, $compile) {

  function onIntroAfterChange(targetElement, scope) {
    angular.element(document.querySelector(".introjs-tooltiptext"))
      .append($compile(
          angular.element(targetElement).attr("data-template"))
        (scope)).html()
  }

  $scope.onIntroAfterChange = onIntroAfterChange;

  $scope.IntroOptions = {
    steps: [{
      element: "#step1",
      intro: "Click the button:",
      position: 'bottom'
    }]
  };
}

Полный HTML

<body ng-app="app" ng-controller="appController">
  <div ng-intro-options="IntroOptions" ng-intro-autostart="true" ng-intro-onafterchange="onIntroAfterChange">
    <p id="step1" data-template="<button my-directive>Test Directive</button>">
      Text
    </p>
    <button my-directive>Test Directive</button>

Примечание: здесь страшный совет, который вам может понадобиться для переноса кода внутри onIntroAfterChange с $timeout. Надеюсь, вам это не понадобится

PS: На самом деле проблема в том, что мы используем IntroJS из AngularJS. Либы имеют совершенно разные подходы, поэтому их смешивание — это боль.

PPS: Надеюсь, кто-то сможет предложить лучшее решение, чем я.

PPS: Лучшее решение — переписать introJS с использованием директив Angular.

person Igor Tsvetkoff    schedule 16.05.2016

Директивы активируются, когда Angular компилирует шаблоны HTML. В этом случае вам необходимо вручную скомпилировать шаблон с помощью службы $compile. Пример:

var elementToString = function (element) {
    var container = angular.element('p').append(angular.element(element));
    return container.html();
}

var introTemplate = 'Click the button: <button my-directive>Test Directive</button>';
var introContent = $compile(introTemplate)($scope);

$scope.IntroOptions = {
    steps: [
        {
            element: "#step1",
            intro: elementToString(introContent),
            position: 'left'
        }
    ]
};
person S.Klechkovski    schedule 09.05.2016
comment
спасибо, а как использовать $compile в контроллере? $scope.IntroOptions защищен в контроллерах Angular. - person Oam Psy; 13.05.2016
comment
$compile — это сервис, и его также можно внедрить в контроллеры, но если вы будете следовать лучшим практикам, вы обернете это в директиву. - person S.Klechkovski; 13.05.2016
comment
Спасибо за информацию. Если вы можете привести пример использования $compile в контроллере, я буду рад принять его. И под этим я не подразумеваю контроллер внутри директивы. - person Oam Psy; 13.05.2016
comment
Это зависит от вас, где вы решите реализовать логику. Я уже рекомендовал сделать это в директиве. Ваше здоровье! - person S.Klechkovski; 13.05.2016

Бьюсь об заклад, что кнопка не компилируется директивой angular. Если вы поместите точку останова на строку "element.bind('click', function() {" , она никогда не сработает. Можете ли вы опубликовать больше кода, чтобы мы могли определить лучший способ его загрузки?

person Bryan Euton    schedule 16.05.2016