AJAX a Nette – první setkání – snippet uvnitř formuláře háže chybu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
svezij
Člen | 69
+
0
-

Ahojte, předem se chci omluvit, jestli je to hloupá otázka, toto je má první zkušenost s AJAXem v Nette. Mám formulář a uvnitř formuláře tabulku s nějakými daty, konkrétně se jedná o seznam obrázků. Mám to vykresleno následujícím způsobem:

{form uploadImagesForm}
  {* tady je možné uploadovat nové obrázky *}
  {input images} {input upload}

  {* tady je seznam již uložených obrázků *}
  <h3>Uložené obrázky</h3>
  {snippet saved_images}
    <table>
      <tbody>
        {foreach $images as $image}
        <tr>
          <td class="preview"><img src="{$basePath}/{$cesta_k_obrazku}/{$image->id}.jpg" /></td>
          <td class="name">{var $name = 'saved_name_' . $image->id}{input $name}</td>
          <td class="delete">
            <a n:href="deleteImage! $image->id" class="ajax">Smazat</a>
          </td>
        </tr>
        {/foreach}
      </tbody>
    </table>
  {/snippet}

  {input save}
{/form}

Problém je, že když to mám takto, tak mi laděnka háže tuto chybu (označený řádek je ten s inputem saved_name_ID):

Undefined variable: _form

<?php $name = 'saved_name_' . $image->id ;$_input = (is_object($name) ? $name : $_form[$name]); echo $_input->getControl()->addAttributes(array()) ?>

Když odeberu snippet z formuláře, formulář se v pořádku načte, ale při zavolání invalidateControl() se neinvalidují změny. Když kliknu na odkaz Smazat, tak se provede smazání obrázku, ale tabulka zůstane stejná, nepřekreslí se. V prezenteru mám tento kód (v metodě handleDeleteImage($imageId) sledujte, prosím, popisky):

/**
 * Creates form.
 *
 * @param string $name
 * @return Nette\Application\UI\Form
 */
protected function createComponentManageProductImagesForm($name)
{
  $form = new Form($this, $name);
  ...
}

/**
 *
 * @param int $imageId
 */
public function handleDeleteImage($imageId)
{
  $this->productImageRepository->deleteImage($imageId);

  if (!$this->presenter->isAjax()) {
    $this->presenter->redirect('this');
  } else {
    // a) následující volání skončí kódem 500 a chybou: 500 (Internal Server Error)
    $this['uploadImagesForm']->invalidateControl();

    // b), c) ani jedno z následujících volání nepřekreslí tabulku s uloženými obrázky
    $this->invalidateControl();
    $this->invalidateControl('uploadImagesForm');
  }
}

Zkusil jsem tedy ještě jednu věc, a to obalit celý formulář do snippetu a invalidovat ten, ale stále se nic nepřekreslí.

{snippet obalFormulare}
  {form uploadImagesForm}
    ...
  {/form}
{/snippet}

{* a v metodě handleDeleteImage($imageId) pak $this->invalidateControl('obalFormulare'); *}

Omlouvám se také, jestli už zde bylo něco podobného řešené (pravděpodobně ano), něco jsem prošel, ale bohužel mě nenapadlo řešení. Co dělám špatně, a co / jak bych měl změnit? Děkuji.

svezij
Člen | 69
+
0
-

Opět zdravím, našel jsem tento příspěvek (který mimochodem odkazuje na článek Dependent form select with AJAX) a poskytl jsem šabloně svůj formulář. Upravil jsem i metodu handleDeleteImage($imageId) tak, že jsem předal do šablony nově upravené images a vše funguje :-). Řešení:
Latte:

{form uploadImagesForm}
  {* tady je možné uploadovat nové obrázky *}
  {input images} {input upload}

  {* tady je seznam již uložených obrázků *}
  <h3>Uložené obrázky</h3>
  {snippet saved_images}
    <table>
      <tbody>
        {foreach $images as $image}
        <tr>
          <td class="preview"><img src="{$basePath}/{$cesta_k_obrazku}/{$image->id}.jpg" /></td>
          <td class="name">{var $name = 'saved_name_' . $image->id}{input $name}</td>
          <td class="delete">
            <a n:href="deleteImage! $image->id" class="ajax">Smazat</a>
          </td>
        </tr>
        {/foreach}
      </tbody>
    </table>
  {/snippet}

  {input save}
{/form}

Presenter->render<View>() (nebo Presenter->action<Action>()):

public function action<Action>()
{
  ...
  $this->template->_form = $this['uploadImagesForm'];
  ...
}

Presenter->handleDeleteImage($imageId):

public function handleDeleteImage($imageId)
{
  $this->imageRepository->delete($imageId);

  if (!$this->presenter->isAjax()) {
    $this->presenter->redirect('this');
  } else {
    $this->template->images = $this->imageRepository->findAll();

    $this->invalidateControl('saved_images');
  }
}

Tohle mi ještě chvíli nefungovalo, ale jelikož mi po kliknutí na „Smazat“ zmizel náhled obrázku, došlo mi, že musím šabloně znovu předat upravené obrázky $this->template->images = $this->imageRepository->findAll();.
Snad je vše srozumitelné a snad je tohle řešení v pořádku. Díky :-).

Mariocz
Člen | 52
+
0
-

Díky že ses pochlubil s řešením. Pomohlo mi .)