Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

createStep() has error: Cannot read property 'parent' of undefined #137

Closed
Watermelonqyu opened this issue Jun 15, 2017 · 17 comments
Closed

Comments

@Watermelonqyu
Copy link

Watermelonqyu commented Jun 15, 2017

I am using the exact versions of the following:

  • Browser: [Chome|Firefox|IE|Safari] Version: x.x
  • AngularJS: 1.6.4
  • Angular Bootstrap: 2.5.0
  • Angular UI Tour: 0.8.1

**I have installed this library via: downloaded package (NPM, Bower, or downloaded package)

I have observed the following behavior:

VM664 angular.min.js:123 TypeError: Cannot read property 'parent' of undefined
    at c (VM675 angular-ui-tour.js:8)
    at Object.h.createStep (VM675 angular-ui-tour.js:8)
    at o.T.createStep (VM675 angular-ui-tour.js:8)
    at b.$scope.createStep (VM602 indexCtrl.js:20)
    at fn (eval at compile (VM664 angular.min.js:239), <anonymous>:4:168)
    at b.$eval (VM664 angular.min.js:148)
    at VM675 angular-ui-tour.js:8
    at l.safeApply (VM675 angular-ui-tour.js:8)
    at VM675 angular-ui-tour.js:8
    at t (VM664 angular.min.js:136) "Possibly unhandled rejection: {}"

This is how I expected it to behave:
create new step

Here is my tour config, and all related step configs:

var tourConfig = {};
<div ui-tour="testTour"></div>
<div id="welcomeElement" ></div>
<div tour-step></div>

Additional notes/code:

$scope.createStep = function(name) {
            var testTour = uiTourService.getTourByName("testTour");
            testTour.createStep({
                elementId: 'welcomeElement',
                stepId: 'clickNext',
                order: 15,
                title: 'new Step',
                content: 'To continue the tour, you need to add a member otherwise you will not see what the prompts are describing.  Either click Previous and follow the instructions or go ahead and add a member.',
                trustedContent: $sce.trustAsHtml('<strong>This can contain HTML, and will override `step.content` if set.</strong>')
            });
        }

plunker: https://plnkr.co/edit/OOn5EtQPmvO57e1vVsLG?p=preview

@benmarch
Copy link
Owner

Hey @Watermelonqyu, I'll need a lot more information to help with this. When does this happen? When you start the tour/before you start the tour? Please provide as much info as you can.

@Watermelonqyu
Copy link
Author

@benmarch Hi, thanks for quick reply.

I just tried it yesterday and can not get the createStep to work. If you click start tour button in Plunker, and click next, you should notice the error. I am not sure if I called the function in a wrong way.

@benmarch
Copy link
Owner

Can you paste a link to your Plunker?

@Watermelonqyu
Copy link
Author

@benmarch I did post in the ticket

Plunker: https://plnkr.co/edit/OOn5EtQPmvO57e1vVsLG?p=preview

@Watermelonqyu
Copy link
Author

@benmarch And I have another question, can we add 2 steps in the same element? I suppose we can not. But I am not sure. Thank you!

@Deklin
Copy link

Deklin commented Jul 21, 2017

I am hitting this one too

@benmarch
Copy link
Owner

It looks like the cause is that the element with the provided ID is not available when the step is shown (it's the only way to get to that line of code). I have added an exception that will let you know if this is the case. Please try again with 0.8.2.

@Watermelonqyu, that's correct, you can only have one step per element when using directives. You can try attaching multiple detached steps to a single element, I haven't tried that.

@Deklin
Copy link

Deklin commented Jul 22, 2017

@benmarch Thank you! I was wondering if it is possible to generate the tour complete in the controller and NOT The html. We have some situations in responsive mode where depending on resolution the component may be display:hidden and we don't want tour items to activate on those but the alternative items that appear when in lower resolutions.

Thanks kindly

@benmarch
Copy link
Owner

It is possible to do so in the controller layer by using TourService.createDetachedTour() and then tour.createStep(). However, you can also achieve the same result by using the tour-step-enabled attribute on each step and using an Angular expression to determine whether or not a step can show based on the screen size.

@Watermelonqyu
Copy link
Author

@benmarch

Thank you very much for the updates! I will try again with 0.8.2 and let you know how it goes.

@Deklin
Copy link

Deklin commented Jul 23, 2017

@benmarch i am still getting this error.

Basically i'm trying to do the entire tour through javascript and not in html as i'm using custom components and sometimes I need to use deeper locators than what is available in the current html template im using.

Basically I am doing this:

In the template:
ui-tour="images-tour" ui-tour-append-to-body="false" ui-tour-on-ready="vm.uiTourOnReadyHandler(tour)">



vm.uiTourOnReadyHandler = function(tour) {
            $translate.onReady().then(function() {
                tour.createStep({
                    elementId: angular.element('#header'),
                    stepId: 'search',
                    order: 1,
                    title: 'foo',
                    content: 'bar'                    
                });                
                
                tour.createStep({
                    elementId: angular.element('#filter'),
                    stepId: 'filter',
                    order: 2,
                    title: 'test',
                    content: 'test'
                });
                //                    trustedContent: $sce.trustAsHtml('<strong>This can contain HTML, and will override `step.content` if set.</strong>')
            });
        };

I have a button initiating this

     var tour = uiTourService.getTourByName('images-tour');
      tour.start();

Which yields
screen shot 2017-07-23 at 7 02 30 pm

@Deklin
Copy link

Deklin commented Jul 23, 2017

Same issue with detached tour

           var tour = uiTourService.createDetachedTour('images');
            
            tour.createStep({
                elementId: angular.element('#header'),
                stepId: 'search',
                order: 1,
                title: 'foo',
                content: 'bar'
            });

            tour.createStep({
                elementId: angular.element('#filter'),
                stepId: 'filter',
                order: 2,
                title: 'test',
                content: 'test'
            });

@Deklin
Copy link

Deklin commented Jul 23, 2017

Ok after some playing around, I finally got it working

Had to set appendToBody to true
backdrop:false on root
and change elementId to element.

var tour = uiTourService.createDetachedTour('images-tour', {
                name: 'images-tour',
                backdrop: false,
                debug: true,
                appendToBody: true
            });

            tour.createStep({
                element: angular.element('#header'),
                stepId: 'search',
                order: 1,
                title: 'foo',
                content: 'bar',
                placement: 'bottom',
                backdrop: true
            });

            tour.createStep({
                element: angular.element('#filter'),
                stepId: 'filter',
                order: 1,
                title: $translate.instant('cloud-composer-ui.images.tour.searching.header'),
                content: $translate.instant('cloud-composer-ui.images.tour.searching.description'),
                placement: 'right',
                backdrop: true
            });

@Watermelonqyu
Copy link
Author

@Deklin

Thank you for the post. I got it working after setting the appendToBody true in the uiTour.
However, i tried to set appendToBody inside createStep, it didn't work. And elementId didn't work as you said.

Here is the plunker: https://plnkr.co/edit/OOn5EtQPmvO57e1vVsLG?p=preview

@benmarch
Copy link
Owner

@Deklin it is best to use elementId instead of element because element requires that the element is present at the time you create the step. When you use elementId, AUIT will check to see if the element exists just prior to showing the popover. However, when you use elementId, just pass the ID string instead of a reference to the element. For example, instead of elementId: angular.element('#header') use elementId: 'header'.

@Deklin
Copy link

Deklin commented Jul 24, 2017

@benmarch Thanks Can I support this type of syntax w/ element id?

'#header button[name="action_filter"]:visible, #filter:visible'

Basically in a jquery style filter this would be Find the first match, if no match, find the second,

Your example seems to be very ID specific vs a jquery style filter hence the usage of element

@benmarch
Copy link
Owner

Hey @Deklin, sorry for the delayed response. I could open it up to any CSS selector, but you still wouldn't be able to use the :visible pseudo-selector. At one point I set up the enabled flag to default to false if the element is not visible. I could look into reenabling that (or why I removed it in the first place). It would be fairly easy to get the visible aspect working yourself. You could create a function on the scope (or controller) that checks if the element is visible onShow, and if not, then set the enabled flag to false. Here is the jQuery source for checking if an element is visible: https://github.com/jquery/jquery/blob/2d4f53416e5f74fa98e0c1d66b6f3c285a12f0ce/src/css/hiddenVisibleSelectors.js#L11

Let's move this conversation over to #141. Is the original issue resolved as of 0.8.2? I can't tell from the comments if you are still seeing the original issue or if it evolved into a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants