[Frage] Erstellen und validieren von verschachtelten Formularen (Create an and validate Parent/Child Objects) TYPO3-Version: 6.2.7

  • ironpfu ironpfu
    R2-D2
    0 x
    99 Beiträge
    1 Hilfreiche Beiträge
    12. 08. 2015, 16:00

    Hallo zusammen,

    Im Zuge meiner Recherchen zu dem folgenden Post:
    [url]http://www.typo3.net/forum/thematik/zeige/thema/120704/[/url]
    musste ich feststellen, dass dieses Thema doch etwas komplexer ist als ursprünglich angenommen.

    Problem:
    Erstellen eines Parent Obejektes (submission) und beliebig vielen Childs (authors) [1:n] mittes Fluid.

    Lösung:
    Zuersten dem Propertymapper konfigurieren:

    1. public function initializeCreateAction() {
    2. $this->arguments->getArgument('newSubmission')->getPropertyMappingConfiguration()->allowProperties('authors');
    3. $this->arguments->getArgument('newSubmission')->getPropertyMappingConfiguration()->allowCreationForSubProperty('authors.*');
    4. $this->arguments->getArgument('newSubmission')->getPropertyMappingConfiguration()->forProperty('authors.*')->allowProperties('firstname');
    5.  
    6. }

    Das Template entsprechend anpassen:

    1. <f:form action="create" name="newSubmission" object="{newSubmission}">
    2. <f:form.textfield property="title" />
    3. <f:form.textfield name="newSubmission[authors][1][firstname]" value="{newSubmission.authors.1.firstname}"/>
    4. </f:form>

    Und schon funktioniert das Anlegen eines neuen Objects "Submission" inkl. Child "Authors".
    Die Validierung im Domain Model wird ebenfalls geprüft.

    Probleme:

    • Child Objects können nur mit "name" und "value" Eigenschaft erstellt werden. Es funktioniert nicht mit der gewollten "property" über den Propertymapper.
    • Hier liegt wahrscheinlich auch der Fehler begraben, dass alle Felder Vzwar validiert werden, aber die fehlerbehafteten Felder nicht an das Fluid Template zurück gegeben werden:
      [b]No value found for key "TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper->formObject"[/b]

    Ich muss hier igendwo ein Brett vor dem Kopf haben, dass diese Funktionlatitäten von so einem mächtigen Framework nicht unterstützt werden?


  • 1
  • ironpfu ironpfu
    R2-D2
    0 x
    99 Beiträge
    1 Hilfreiche Beiträge
    13. 08. 2015, 21:15

    Hat wirklich niemand einen Tipp?
    Ich bin ein wenig weitergekommen. Folgende Änderungen im Controller und in der View erlauben mir nach einem Validierungsfehler die Erstellung des ursprünglich dynamisch generierten Formulars.

    Im Controller:

    1. /**
    2. * action new
    3. *
    4. * @param \PCON\Congress\Domain\Model\Submission $newSubmission
    5.   * @dontvalidate $newSubmission
    6. * @return void
    7. */
    8. public function newAction(\PCON\Congress\Domain\Model\Submission $newSubmission = NULL) {
    9.  
    10. $this->view->assign('newSubmission', $newSubmission);
    11.  
    12. // This is for Error Handling in author child object
    13. if($this->request->getOriginalRequest()!= NULL)
    14. {
    15.  
    16. $argument = $this->request->getOriginalRequest()->getArgument('newSubmission');
    17. $this->view->assign('authors', $argument['authors']);
    18. }
    19.  
    20.  
    21. }

    1. <f:for each="{authors}" as="author" key="uid" iteration="iterator">
    2. <f:form.textfield property="authors.{uid}.firstname" placeholder="Enter your first given name" />
    3. </f:for>

    Die Validierung funktioniert ebenfalls. Leider werden die Fehlerhaften Felder noch immer nicht mit der "f3-form-error" Klasse gerendert. Schuld dafür dürfte der PropertyMapper sein (Bzw. meine falsche Konfiguration). Ein Debug der Mapping Results zeigt, dass die Child Objekte nicht die von mir definierte UID bekommen sondern einen hash.

    1. $result = $this->getControllerContext()->getRequest()->getOriginalRequestMappingResults();

    1. array(19 items)
    2. newSubmission.type => array(1 item)
    3. 0 => TYPO3\CMS\Extbase\Validation\Errorprototypeobject
    4. message => 'The given subject was NULL.' (27 chars)
    5. code => 1221560910 (integer)
    6. arguments => array(empty)
    7. title => '' (0 chars)
    8. newSubmission.authors.000000006200d7b200007f3972b36107.email => array(1 item)
    9. 0 => TYPO3\CMS\Extbase\Validation\Errorprototypeobject
    10. message => 'The given subject was not a valid email address.' (48 chars)
    11. code => 1221559976 (integer)
    12. arguments => array(empty)
    13. title => '' (0 chars)
    14. newSubmission.authors.000000006200d7b400007f3972b36107.email => array(1 item)
    15. 0 => TYPO3\CMS\Extbase\Validation\Errorprototypeobject
    16. message => 'The given subject was not a valid email address.' (48 chars)
    17. code => 1221559976 (integer)
    18. arguments => array(empty)
    19. title => '' (0 chars)
    20. newSubmission.authors.000000006200d7b700007f3972b36107.email => array(1 item)
    21. 0 => TYPO3\CMS\Extbase\Validation\Errorprototypeobject
    22. message => 'The given subject was not a valid email address.' (48 chars)
    23. code => 1221559976 (integer)
    24. arguments => array(empty)
    25. title => '' (0 chars)

    Kann mir irgendjemand eine saubere Lösung nennen?

  • ironpfu ironpfu
    R2-D2
    1 x
    99 Beiträge
    1 Hilfreiche Beiträge
    18. 08. 2015, 14:50

    Ich kann mir wirklich nicht vorstellen, dass keiner dieses Problem hat bzw. keiner eine Lösung hat....
    Nach ca. 1000000000h Forensuche habe die aus meiner Sicht die "schmutzigste Lösung" überhaupt:

    Ich überschreibe einfach in der errorAction die Werte (was natürlich ganz im Sinne von Extbase ist B-)):
    Wäreüber eine RICHTIGE LÖSUNG dankbar!

    1. protected function errorAction() {
    2.  
    3.  
    4. //\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->arguments->getValidationResults()->forProperty('newSubmission.authors'));
    5. $authorErrors = $this->arguments->getValidationResults()->forProperty('newSubmission.authors')->getSubResults();
    6.  
    7. $i = 1;
    8. foreach ( $authorErrors as $uid => $author) {
    9. foreach ( $author->getSubResults() as $property => $error) {
    10. $this->arguments->getValidationResults()->forProperty('newSubmission.authors.'.$i.'.'.$property)->addError(new \TYPO3\CMS\Extbase\Error\Error('Error', time()));
    11. }
    12. $i++;
    13. }
    14. }

  • Ei-Dotter Ei-Dotter
    Jedi-Ritter
    0 x
    137 Beiträge
    1 Hilfreiche Beiträge
    12. 04. 2016, 01:52

    Ich kenne auch nicht die "bessere" Lösung, aber Dein Ansatz hat mit echt weitergeholfen und bei mir auch funktioniert.

    Danke!

  • Jan.S Jan.S
    Padawan
    0 x
    38 Beiträge
    0 Hilfreiche Beiträge
    09. 09. 2016, 11:11

    Gibt es bis heute wirklich keine saubere Lösung um die Error Klassen an die Kind Objekte zu bekommen?

    Ich kann es garnicht glauben und werde noch etwas weiter suchen :'(

  • ironpfu ironpfu
    R2-D2
    0 x
    99 Beiträge
    1 Hilfreiche Beiträge
    14. 11. 2016, 13:32

    Hi,

    das Thema ist zwa schon etwas alt aber anscheinend noch immer aktiv...
    Hier einige Updates:

    Zur Frage von Jan.S.:
    Muss ich am Ende der errorAction noch ein redirect auf die update Action durchführen?

    1. $referringRequest = $this->request->getReferringRequest();
    2.  
    3. if ($referringRequest !== NULL) {
    4. $originalRequest = clone $this->request;
    5. $this->request->setOriginalRequest($originalRequest);
    6. $this->request->setOriginalRequestMappingResults($this->arguments->getValidationResults());
    7. $this->forward($referringRequest->getControllerActionName(), $referringRequest->getControllerName(), $referringRequest->getControllerExtensionName(), $referringRequest->getArguments());
    8. }

    Punkt 2: Sauberere Lösung...
    Nicht Sauberer aber effektiver...
    Ich mache die gesamte Validierung im Controller.
    in der initializeCreateAction rufe ich den ValidatorResolver auf und erledige die Validaierung je nach Bedarf über BaseValidatorConjunction oder eigenen Validator:

    1. /** @var TYPO3\CMS\Extbase\Validation\ValidatorResolver $validatorResolver */
    2. $validatorResolver = $this->objectManager->get('TYPO3\CMS\Extbase\Validation\ValidatorResolver');
    3. $myValidator = $validatorResolver->getBaseValidatorConjunction('xxx\xxx\Domain\Model\NewModelXXX');

    Good Luck!

  • 1