Ajaxový formulář se „překreslí“ před jeho odesláním

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

Ahoj mám trochu problém s formulářem..zřejmě moje blbost..ale nedaří se mi zjistit, kde dělám chybu

Čeho chci docílit

Pod tabulkou mám přidávací formulář se selectem. Výběrem položky v select a kliknutím na „assign“ chci přidat položku do tabulky a zároveň danou položku odstranit ze selectu.

S čím mám problém

Formulář se ve snippetu překreslí dříve, než se uloží data v onSuccess. Výsledkem je že v čase t+1 zmízí ze selectu položka přidaná v čase t.

Jak vytvářím formulář

class MKitFormFactory extends AbstractFormFactory {

  public function create(\App\Model\Dao\Measurement $measurement) {
    $this->measurement = $measurement;
    $kits = $this->measurementManager->getAvailableKits($measurement->getId());
    $form = new Form;
    $form->addSelect('kitid', 'Kit', $kits);
    $form->onSuccess[] = array($this, 'formSucceeded');
    $form->onValidate[] = array($this, 'formValidation');
    $form->addSubmit('assign', 'Assign');
    // Renderer bootstrap - true, ajax - true
    return $this->updateRenderer($form, true, true);
  }

  public function formSucceeded($form, $values) {
    $this->db->begin();
    try {
      $mid = $this->measurement->getId();
      $kid = $values->kitid;
      $form->setValues(array(), true);
      (new MeasurementKit())->setDb($this->db)->create($mid, $kid);
    } catch (\Exception $e) {
      $this->db->rollback();
      $form->addError($e->getMessage());
    }
    $this->db->commit();
  }
...
}

Jak s ním pracuji v presenteru

protected function createComponentMKitForm() {
  $measurement = $this->createDao("Measurement", $this->id);
  $form = $this->mKitFactory->create($measurement);
  $form->onSuccess[] = function ($form) {
    $this->reloadKitData();
    $this->redrawControl('analysisContainer');
    $this->redrawControl('kitContainer');
  };
  return $form;
}

Jak ho vypisuji v latte

<h2>Kits</h2>
<div class="controls">
  <div n:snippet="kitContainer">
    {if count($kits) == 0}
      <p>Please assign at least one KIT to this measurement. Kit name must
        match the name of KIT that was used during measurement process. If
        you want to automatize this process please use our .RET templates
        for Rotorgene.
      </p>
    {else}
      <table class="table table-striped">
        <tbody>
          {foreach $kits as $kit}
            <tr>
              <td>
                <a href="{plink Kit:, 'uname' => $kit->getUName()}">{$kit->getName()}</a>
              </td>
              <td>
                <a class="ajax btn btn-default btn-xs" href="{link removeKit!, 'kid' => $kit->getId()}">Remove</a>
              </td>
            </tr>
          {/foreach}
        </tbody>
      </table>
    {/if}
    <div class="controls-row">
      {form mKitForm}
        <div class="controls-row">
          <span class="span1">
            {input kitid}
            {input assign}
          </span>
        </div>
      {/form}
    </div>
  </div>
</div>

Poznámky

Zkoušel jsem trasovat posloupnost operací po odeslání formuláře

  1. Nejprve se zavolala metoda createComponentMKitForm (nechápu proč)
  2. Pak se zavolala metoda formSucceeded a data se uložila do databáze
  3. Pak se zavolal callback (function ($form)) a překreslil se snippet, ALE zatímco v tabulce se objevil nově přidaný prvek, formulář odpovídal stavu 1) (zde už se vytváření formuláře nevolalo)

Tato posloupnost zapříčiňuje, že se data pro formulář pomocí getAvailableKits vyberou dříve než se formulář uloží a proto to zpoždění v updatu selectu.

Poradíte, co dělám špatně?

David Matějka
Moderator | 6445
+
+2
-

Nejprve se zavolala metoda createComponentMKitForm (nechápu proč)

pred zpracovanim se musi ten formular vytvorit, aby se vedelo, jaka je jeho struktura, validacni pravidla, polozky, typy, jake jsou callbacky atd.

reseni:
ve zpracovani formu proste z tech polozek v kitid tu jednu odeber (treba jen getItems, unset a setItems znovu)

microcz
Člen | 62
+
0
-

Děkuju moc Davide ..pomohlo, přikládám funkční řešení

protected function createComponentMKitForm() {
  $measurement = $this->createDao("Measurement", $this->id);
  $form = $this->mKitFactory->create($measurement);
  $form->onSuccess[] = function ($form) {
    // BEGIN NOVE
    $form['kitid']->setItems($this->measurementManager->getAvailableKits($this->id));
    // END NOVE
    $this->reloadKitData();
    $this->redrawControl('analysisContainer');
    $this->redrawControl('kitContainer');
  };
  return $form;
}

Editoval microcz (26. 5. 2015 14:35)