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

Dynamically loading nested pjax #13493

Closed
friek108 opened this issue Feb 1, 2017 · 15 comments
Closed

Dynamically loading nested pjax #13493

friek108 opened this issue Feb 1, 2017 · 15 comments
Labels
feature:pjax status:to be verified Needs to be reproduced and validated.

Comments

@friek108
Copy link

friek108 commented Feb 1, 2017

What steps will reproduce the problem?

I have a main pjax container that I use to navigate between pages. One one of these pages, I dynamically load in a page and the page includes some content and a grid. The grid itself is wrapped in a pjax widget.

When I set a filter on the grid, a request is sent to update the outer pjax container which is immediately cancelled and replaced by a request to update the nested grid pjax. The nested container updates correctly.

When I click on a sort link however, the outer container is used and updated with only the 'grid' (leaving my other page content to be replaced).

Further Info:

  • If I load the grid page through a browser refresh, everything works as expected. It is only when you load the 'grid page' dynamically (in the outer container).
  • skipOuterContainers is set to true in the grid pjax wrapper.
  • From the controller, I use:
    if (Yii::$app->request->isPjax) return $this->renderAjax('myView'); else return $this->render('myView')
    This is because I need to load some dynamically loaded scripts (for eg. yii.Gridview.js and others).
  • I'm using a different filterUrl on the grid to return only the grid content (rather than the grid and the other content on the page).

What is the expected result?

Nested container updates.

What do you get instead?

Outer container updates and is replaced by the nested container content.

Additional info

Q A
Yii version 2.0.11-dev
PHP version 5.5.12
Operating system Windows
@yii-bot
Copy link

yii-bot commented Feb 2, 2017

Thanks for posting in our issue tracker.
In order to properly assist you, we need additional information:

  • When does the issue occur?
  • What do you see?
  • What was the expected result?
  • Can you supply us with a stacktrace? (optional)
  • Do you have exact code to reproduce it? Maybe a PHPUnit tests that fails? (optional)

Thanks!

This is an automated comment, triggered by adding the label status:need more info.

@samdark
Copy link
Member

samdark commented Feb 2, 2017

It sounds rather vague about how to reproduce it. Would you please supply us with more details? If you'll start with basic application template and do as little changes as possible while still getting the issue, it would be perfect. Thanks.

@friek108
Copy link
Author

friek108 commented Feb 3, 2017

I've created an example from basic application template here. You can also view the respository here.

To reproduce:

  1. Go to the about page, then refresh it. After refresh, sort the grid. This works as expected.
  2. Go to home page, then refresh it. Then navigate to 'about' page. Sort the grid. Incorrectly uses the outer container.

Modified files

  • /controllers/SiteController.php (about and about-grid actions only)
  • /views/layouts/main
  • /views/site/about
  • /views/site/about-grid
  • /config/web.php & .htaccess (for pretty urls only)

@samdark samdark added status:to be verified Needs to be reproduced and validated. and removed status:need more info labels Feb 3, 2017
@friek108
Copy link
Author

friek108 commented Feb 4, 2017

Perhaps nested Pjax should be considered just plain Ajax and handled separately?

In general, it's hard to know the correct way to design and optimise an application beyond simple use cases. Eg. Loading js assets on separate pages (in a container), using a menu which might be outside a pjax container, nested pjax, etc.

@samdark
Copy link
Member

samdark commented Feb 4, 2017

Yes, it is rather complicated usage.

@derekisbusy
Copy link
Contributor

derekisbusy commented Feb 4, 2017

@samdark not really...

Remove the line...

$this->registerJs('jQuery(document).pjax(".navbar-nav a", {"push":true,"replace":false,"timeout":5500,"scrollTo":false,"container":"#pjax-page-container"}); ');

from your layout. The yii2 pjax widget creates this automatically. This is why you are triggering two pjax events.

You can move your settings to the widgets clientOptions setting and the settings will be passed to the pjax jQuery widget.

Pjax::begin([
          'id'=>'pjax-page-container',
          'timeout'=>5500,
            'clientOptions' => ["push" => true,"replace" => false,"timeout" => 5500,"scrollTo" => false,"container" => "#pjax-page-container"]
        ]);

I sent you a pull request with the changes friek108/yii2-basic/pull/1

@skworden
Copy link

skworden commented Feb 5, 2017

@friek108 I had almost the exact same issue with the sort option (my tables are ajax loaded inside of tabs with pjax wrappers and it just updates the parent instead of child pjax). I removed the child pjax and am just using ajax. Here is something similar to what I'm using until this is fixed. I removed all of my unnecessary stuff so hopefully it still works.

jQuery(document).on('click', 'table thead *[data-sort]', function (e) {
    e.preventDefault();
    jQuery.ajax({
        url: jQuery(this).attr('href'),
        type: 'GET',
        success: function (data) {
            jQuery(this).closest('[data-pjax-container]').html(data);
        }
    });
});

@derekisbusy
Copy link
Contributor

@friek108 I just ran into the same issue the other day with ajax tabs. I fixed it by registering the pjax assets in the parent view.

@skworden
Copy link

skworden commented Feb 5, 2017

@derekisbusy How do you tell it to not register in the child views or do you manually call pjax in those views via jQuery?

@derekisbusy
Copy link
Contributor

You use renderPartial() instead of render() in your controller.

@friek108
Copy link
Author

friek108 commented Feb 6, 2017

@derekisbusy your first answer isn't correct, that line was pertaining to .navbar-nav a (outside the pjax container, didn't want to put my menu in the pjax container), this shouldn't affect anything.

@skworden thanks for the code, did you have any code for the filters as well as the sort?

@derekisbusy @skworden I get putting pjax code in the parent view, but what if say, you want to 'reinitialise' the grid with some js each time. For example, say you wanted to init select2 as a filter?

@friek108
Copy link
Author

friek108 commented Feb 6, 2017

Thanks for the feedback. Very basic example updated and working: friek108/yii2-basic@e597b49
Check out the demo here

What do you think of this approach?

@derekisbusy
Copy link
Contributor

derekisbusy commented Feb 6, 2017

Yes but it no longer has nested pjax and this requires you to write ajax calls for all your widgets. Would be nicer to have a solution that works all around. I actually ran into this same issue with pjax about a year ago. I spent a day trying to rewrite the pjax script but then decided not to use nested pjax instead. It has to do with the way pjax was written. You need to be able to unbind and rebind the pjax widget to elements and pjax was not written using the widget factory so it's state is hard to manage.

I managed to fix the issues without rewriting pjax. #13545

@samdark
Copy link
Member

samdark commented Feb 6, 2017

Yeah. I guess Yii team can't do anything about it except total rewrite of PJAX library itself which isn't what we want to do anytime soon.

@samdark samdark closed this as completed Feb 6, 2017
@friek108
Copy link
Author

friek108 commented Feb 6, 2017

Ok, just so I understand what you're saying is when loading the inner container dynamically, you could:

  • destroy the outer pjax container and then re-initialise both the inner and outer pjax; or
  • push the inner container pjax code to the start of the queue.

but this is not possible with pjax. Ajax is most likely a better solution anyway..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature:pjax status:to be verified Needs to be reproduced and validated.
Projects
None yet
Development

No branches or pull requests

5 participants