Snippet in a snippet doesn't see a varible

Notice: This thread is very old.
netteman
Member | 122
+
0
-

Hi,

this is what I'm trying to achieve

  1. user load the page
  2. an ajax request loads information from database and appends it to the first snippet (several rows)
  3. a user can try to load updated information by clicking on a link (only one row is loaded and changed in DOM)
<div n:snippet="newText" data-ajax-append="true">
{ifset $ajaxTexts}
    {foreach $ajaxTexts as $text}
        {$text->text}<br />
         <li n:snippet="item-$text->id">{$text->text} <a class="ajax" n:href="update! $text->id">update</a></li>
    {/foreach}

{/ifset}
</div>

I can't get the “clicking part” working because Nette says $text is undefined.

This example with snippets within a snippet works https://doc.nette.org/…ication/ajax#… but when I add the AJAX append the inner snippet doesn't see the variable.

Can I make it work somehow? Thanks :)

Last edited by netteman (2016-07-04 15:38)

David Matějka
Moderator | 6445
+
0
-

Hi, could you please show the compiled template (it's in a /temp/cache/latte directory)?

David Grudl
Nette Core | 8082
+
0
-

It is expected behavior.

David Matějka
Moderator | 6445
+
0
-

@DavidGrudl I think it's not. <li> is a dynamic snippet so the $text variable should be visible.

netteman
Member | 122
+
0
-

New behaviour of the page (the code is the same): it doesn't say that $text is undefined anymore. This time the presence of the inner snippet corrupts the JSON response

For David Matějka: cached latte

<?php

use Latte\Runtime as LR;

class Template51785242ca extends Latte\Template
{
	public $blocks = [
		'content' => 'blockContent',
		'_newText' => 'blockNewText',
	];

	public $blockTypes = [
		'content' => 'html',
		'_newText' => 'html',
	];


	function render()
	{

		// prolog Latte\Macros\CoreMacros
		if ($this->initialize($_args)) return;
		extract($_args);
		if (isset($this->params['text'])) trigger_error('Variable $text overwritten in foreach on line 22');

		// prolog Nette\Bridges\ApplicationLatte\UIMacros
		if (Nette\Bridges\ApplicationLatte\UIRuntime::initialize($this, $this->blockQueue)) return;

		// main template
		call_user_func(reset($this->blockQueue['content']), get_defined_vars());
?>

<?php
	}


	function prepare()
	{
		extract($this->params);
		$this->parentName = $this->parentName ?: ($this->blocks && !$this->getReferringTemplate()
		&& isset($this->global->uiControl) && $this->global->uiControl instanceof Nette\Application\UI\Presenter
		? $this->global->uiControl->findLayoutTemplateFile() : NULL);
		return get_defined_vars();
	}


	function blockContent($_args)
	{
		extract($_args);
?>

        Once upon a time... <br>


        <div data-ajax-append="true"<?php echo ' id="' . $this->global->uiControl->getSnippetId('newText') . '"' ?>>
<?php call_user_func(reset($this->blockQueue['_newText']), $this->params) ?>
        </div>




<?php
		/* line 32 */ $_tmp = $this->global->uiControl->getComponent("textForm");
		if ($_tmp instanceof Nette\Application\UI\IRenderable) $_tmp->redrawControl(NULL, FALSE);
		$_tmp->render();
?>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
	<script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
        <script src="<?php echo LR\Filters::escapeHtmlAttr(LR\Filters::safeUrl($basePath)) /* line 35 */ ?>/js/main.js"></script>
        <script src="<?php echo LR\Filters::escapeHtmlAttr(LR\Filters::safeUrl($basePath)) /* line 36 */ ?>/js/nette.ajax.js"></script>
        <script>
        $(function () {
            $.nette.init();
        });

        $(document).ready(

        function() {
            $.nette.ajax({
                url: '?do=firstLoad&roomId=2'
            })
        });

        $(document).ready(

            function() {
                setInterval(function(){
                    $.nette.ajax({
                        url: '?do=newText&roomId=2'
                    })
                }, 10000);
            });
        </script>

<?php
	}


	function blockNewText($_args)
	{
		extract($_args);
		$this->global->uiControl->redrawControl('newText', FALSE);

		?>        <?php
		if (isset($ajaxTexts)) {
?>

<?php
			$iterations = 0;
			foreach ($ajaxTexts as $text) {
				?>                <?php echo LR\Filters::escapeHtml($text->text) /* line 23 */ ?><br>
                <li<?php echo ' id="' . ($this->global->dynSnippetId = $this->global->uiControl->getSnippetId("item-$text->id")) . '"' ?>><?php
				ob_start();
				echo LR\Filters::escapeHtml($text->text) /* line 24 */ ?> <a class="ajax" href="<?php echo LR\Filters::escapeHtmlAttr($this->global->uiControl->link("update!", [$text->id])) ?>">update</a><?php
				$this->global->dynSnippets[$this->global->dynSnippetId] = ob_get_flush();
?></li>
<?php
				$iterations++;
			}
		}
		if (isset($this->global->dynSnippets)) return $this->global->dynSnippets;

	}

}

This is the working JSON response of firstLoad() – no inner snippets in the template

snippet--newText:"
                first<br>
                second<br>
                third<br>"

This is the probably corrupted JSON response of firstLoad() – inner snippets are part of the template

snippet--item-1:"first <a class="ajax" href="/storry-2/www/room/default/1?roomId=2&amp;do=update">update</a>"
snippet--item-2:"second <a class="ajax" href="/storry-2/www/room/default/2?roomId=2&amp;do=update">update</a>"
snippet--item-3:"third <a class="ajax" href="/storry-2/www/room/default/3?roomId=2&amp;do=update">update</a>"
David Matějka
Moderator | 6445
+
0
-

This response is expected. I think you will have to write custom JS success handler for appending new items.

netteman
Member | 122
+
0
-

Ok, thanks :)