IntroJS Add Directive To Step Markup

萝らか妹 提交于 2020-01-03 17:15:14

问题


I am using introJS to have a user guide. I can show various features, however, i want to add a directive to the markup e.g:

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

With the above, i can see the text 'Click the button' plus a default button.

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

However, with the above. The console.log is never displayed, yet when i inspect the markup, i can see:

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

If i place the directive any where else in my application, the console.log is successful.


回答1:


Maybe this can help you.

I've tried to implement @S.Klechkovski's solution here, it failed for me. But let anyone experiment with this.

But actually, I've made something you want here:

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'
    }]
  };
}

(the hint is to use ng-intro-onAfterChange to compile there using proper scope) The bad part is that I've hard-coded the template there.

But you can go further and set the template as an attribute of the element you want to show tooltip on. Had no possibility to access intro field of a step. So... Sory for that extreme level of coding pornography here (it seems to be working):

Full 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'
    }]
  };
}

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

Note: here is the scary tip that you might need to wrap the code inside the onIntroAfterChange with $timeout. Hope you won't need it

PS: Actually the problem is that we are using IntroJS from AngularJS. Libs have completely different approaches, so mixing them is a pain.

PPS: Hope someone could provide better solution than I did.

PPS: The best solution is too rewrite introJS using Angular directives




回答2:


Directives are activated when Angular compiles the HTML templates. In this case you need to manually compile the template using the $compile service. Example:

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'
        }
    ]
};



回答3:


I bet that the button isn't getting compiled by the angular directive. If you put a breakpoint on the line "element.bind('click', function() {" it would never be hit. Can you post more of the code so that we can determine the best way to make it load?



来源:https://stackoverflow.com/questions/37055468/introjs-add-directive-to-step-markup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!