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

Method redrawControl() doesn't work in Nette 2.2 (in some cases) #1498

Closed
janreges opened this issue May 28, 2014 · 13 comments

Comments

Projects
None yet
5 participants
@janreges
Copy link

commented May 28, 2014

After upgrade to Nette 2.2, method redrawControl() doesn't work as expected in some our projects.

When i have simple snippet, which is invalidated by signal, it works great.

When i have form in snippet "myForm" and form is sent by ajaxSubmit(), form is successfully processed with inserted "thank you message", but $this->redrawControl('myForm'); doesn't work. Ajax response body is whole HTML page with empty JSON after HTML, instead of JSON only.

With enabled output buffering by ob_start(), response looks like:

...
</body>
</html>
{"state":[]}

With disabled output buffering, error below occurs (whole HTML is sent ahead of JSON, which is trying to set json header):

Cannot send header after HTTP headers have been sent

See also: http://forum.nette.org/cs/17836-cannot-send-header-after-http-ajaxovy-pozadavek

Do you have any ideas? Before upgrade to Nette 2.2 it worked perfectly.

@dg

This comment has been minimized.

Copy link
Member

commented May 28, 2014

Can you create example, based on sandbox?

@janreges

This comment has been minimized.

Copy link
Author

commented May 28, 2014

After 1 hour, i'm not able to simulate this bug in sandbox :-(

In my debugging, i located final difference in sandbox and in my project.

Below is run() method in Nette\Application\UI\Presenter.

In sandbox, after my ajax request, calling "$this->response->send()" has no output, but in my project, it send whole page HTML to output.

Any ideas about conditions, when this method send output and when not?

Thank you.

..
if ($this->isAjax()) try {
    $hasPayload = (array) $this->payload; unset($hasPayload['state']);
    if ($this->response instanceof Responses\TextResponse && $this->isControlInvalid()) { // snippets - TODO
        $this->snippetMode = TRUE;
        $this->response->send($this->httpRequest, $this->httpResponse); // <- in sandbox it has no output, in my project is printed whole HTML page
        die('END');
        $this->sendPayload();
    } elseif (!$this->response && $hasPayload) { // back compatibility for use terminate() instead of sendPayload()
        $this->sendPayload();
    }
} catch (Application\AbortException $e) { }
....
@dg

This comment has been minimized.

Copy link
Member

commented May 28, 2014

Co je před voláním send() obsahem $this->response->getSource()? Pokud to není objekt Nette\Application\UI\ITemplate, snippety fungovat nebudou.

Mohl by pomoci tento commit nette/application@c79b7fe

@janreges

This comment has been minimized.

Copy link
Author

commented May 28, 2014

On both sides (sandbox and my project) is instance of Nette\Bridges\ApplicationLatte\Template and it implements Nette\Application\UI\ITemplate.

So, your commit doesn't work in my case :(

@janreges

This comment has been minimized.

Copy link
Author

commented May 28, 2014

Still one hint.. on both sides is executed block below (in compiled template), but in sandbox method renderChildTemplate() returns NULL and in my project it returns whole HTML.

<?php if ($_l->extends) { ob_end_clean(); return $template->renderChildTemplate($_l->extends, get_defined_vars()); }

Variable $template on both sides is also instance of Nette\Bridges\ApplicationLatte\Template.

@dg

This comment has been minimized.

@janreges

This comment has been minimized.

Copy link
Author

commented May 29, 2014

My fail, sorry.

I wrote "it returns", but I thought "it sends to output".

@milo

This comment has been minimized.

Copy link
Member

commented May 29, 2014

@janreges If you are looking for a place where the stdout output begins, Tracy\OutputDebugger::start() in the bootstrap may helps you.

@janreges

This comment has been minimized.

Copy link
Author

commented May 29, 2014

@milo, thank you for your tip :)

With enabled OutputDebugger, this is output for Ajax request:

trunk/temp/cache/latte/01-janek-trunk-app-templates-Web-layout-tpl-70292f572d26ffaea9bd4d0c09e0bc2f.php:23 "<!DOCTYPE html>\n<html class="no-js">\n<head>\n\t<meta charset="utf-8">\n\t<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">\n\t<title>Kontakty \xe2 ... " (1224)
trunk/temp/cache/latte/janek-trunk-app-templates-Web-Kontakty-kontakty-tpl-4faa4d9021325d61eaaf2cd60d29a110.php:30 "<nav class="breadcrumbs"> <div class="page-inner"> <ul> <li><a href="/">Úvodní stránka</a></li> <li>Kontakty</li> </ul> </div> </nav> < ... " (11910)
trunk/libs/Nette/Bridges/FormsLatte/FormMacros.php:239 "<form action="/kontakty/" method="post" id="contact-form" class="ajax">" (71) 
trunk/temp/cache/latte/janek-trunk-app-templates-Web-Kontakty-kontakty-tpl-4faa4d9021325d61eaaf2cd60d29a110.php:528 " <div class="input-group"> <label for="email">Váš email <span class="req"></span></label> <input type="email" id="email" placeholder="Vá ... " (2167)
trunk/libs/Nette/Bridges/FormsLatte/FormMacros.php:270 "<div><input type="hidden" name="_token_" id="frm-napisteNamForm-_token_" value="230ak6pkvir3kM+DMHEWzN2kwJWt61WF70trA="><input type="hidden" name="fcr ... " (275) 
trunk/temp/cache/latte/janek-trunk-app-templates-Web-Kontakty-kontakty-tpl-4faa4d9021325d61eaaf2cd60d29a110.php:517 "</div>\t<hr>\n\t<h2>Informace</h2>... " (551)
trunk/temp/cache/latte/01-janek-trunk-app-templates-Web-layout-tpl-70292f572d26ffaea9bd4d0c09e0bc2f.php:77 "     </main> <!-- banner na katalog--> <!-- footer--> </div> <!-- skripty --> " (98) 
trunk/temp/cache/latte/janek-trunk-app-templates-Web-Kontakty-kontakty-tpl-4faa4d9021325d61eaaf2cd60d29a110.php:19 "    <script src="/assets/js/kontakt.js"></script> " (47) 
trunk/temp/cache/latte/01-janek-trunk-app-templates-Web-layout-tpl-70292f572d26ffaea9bd4d0c09e0bc2f.php:84 "     <script type="text/javascript" src="/js/nette/tracy-sql-search.js"></script> </body> </html> " (95) 
trunk/libs/Nette/Application/Responses/JsonResponse.php:71 "{"state":[]}" (12) 
@OndrejSlamecka

This comment has been minimized.

Copy link
Contributor

commented May 31, 2014

@janreges

This comment has been minimized.

Copy link
Author

commented May 31, 2014

@OndrejSlamecka It's definitely the same problem.

It's difficult to build a demonstration based on the sandbox?

@matej21

This comment has been minimized.

Copy link
Contributor

commented Jun 2, 2014

I've finally found it!

See this: http://api.nette.org/2.2.1/source-Bridges.ApplicationLatte.UIMacros.php.html#52
($_l->extends may contain a value in the layout and therefore renderSnippets method is not called)

It is quite tricky to simulate it on the sandbox, because UIMacros::finalize (http://api.nette.org/2.2.1/source-Latte.Macros.BlockMacros.php.html#61) resets $_l->extends to null if there is some named block. And there are few blocks in the sandbox layout.

As a workaround, simply add empty block to your @layout.latte :)

matej21 added a commit to matej21/nette-latte that referenced this issue Jun 2, 2014

@janreges

This comment has been minimized.

Copy link
Author

commented Jun 2, 2014

@matej21 - Great work! Thank you, your workaround works perfectly! :)

@dg - It's bug, or known limitation?

matej21 added a commit to matej21/nette-latte that referenced this issue Jun 2, 2014

dg added a commit to nette/latte that referenced this issue Jun 2, 2014

Macros: local storage $_l split into (really) local $_l and block sto…
…rage $_b, $_l->extends is not shared [Closes #21][Closes nette/nette#1498]

dg added a commit to nette/latte that referenced this issue Jun 2, 2014

dg added a commit to nette/latte that referenced this issue Jun 2, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.