Zum Inhalt springen

Mehrere Objekte in einem Formular erstellen/bearbeiten

Erstellt am 26. April 2013 · 9 Antworten · letzte Antwort am 16. Juni 2013

Tags: Fluid, Frage

BjoernBoba ·

Hallo,
bei meiner Extension stehe ich erneut vor einem Problem, für das mir zur Zeit keine funktionierende Lösung einfällt.
Und zwar möchte ich innerhalb eines Formulars mehrere Objekte des gleichen Typs erstellen, beziehungsweise einen Wert der Objekte befüllen.
Und zwar habe ich beispielsweise mehrere RadioButtons. Nun möchte ich pro RadioButton ein Objekt erstellen, bzw. die Variable "value" eines Objektes befüllen.

In meinem jetzigen Ansatz übergebe ich dem View schon einmal so viele leere Objekte der Klasse Answer, wie ich RadioButtons, oder CheckButtons etc. habe. Allerdings weiß ich nun nicht, wie ich es lösen kann, dass nicht nur ein Objekt bearbeitet wird, sondern für jedes FormObjekt ein anderes der "Answer"-Objekte bearbeitet wird.

Ich bin für jede Hilfe, bzw jeden Tipp dankbar.

Mit freundlichen Grüßen
BjoernBoba

BjoernBoba ·

Push und Edit:
Den ersten Post kann man quasi vernachlässigen...

Guten Tag,
bei der Entwicklung einer Extension stehe ich zur Zeit vor dem Problem, dass ich es nicht hinbekomme mehrere Objekte einer Klasse innerhalb eines Formulars zu erstellen.
Mit der Extension sollen Umfragen erstellt und ausgefüllt werden können. Für jede einzelne Antwort zu einer der ganzen Fragen soll eine Instanz der eben genannten Objekte erstellt werden.
Also bspw. gibt es mehrere TextFields und pro Field soll ein Objekt erstellt und dessen Variable "value" gefüllt werden.

Ich habe auch schon einen passenden Link gefunden:
#106852
Eigentlich sollte das die Lösung des Problems sein, allerdings bekomme ich es nicht lauffähig auf meine Extension übertragen.

Das einzige was bisher passiert, wenn der Submit Button am Ende gedrückt wird ist, dass der View neu geladen wird.
Im folgenden poste ich den betroffenen Code:
Nur zur Erläuterung, die TextFields sind in einem externen Partial angegeben, die mit einem Partial-VH ausgewählt werden.

Show:

{namespace vh=Tx_survey_ViewHelpers}

<f:layout name="Default" />

<f:section name="main">

    <f:form method="post" controller="Session" action="create"
        name="newSession" object="{newSession}" arguments="{survey: survey}">

(...)

            <fieldset>
                <legend>{question.text}</legend>
                <div>{question.subtext}</div>
                <br />

(...)

                        <f:render partial="{vh:partial(type: '{question.type}')}"
                            arguments="{question: question,
                                    options: question.options}" />
(...)

            </fieldset>
            <br />
        </f:for>

        <f:form.submit value="Submit" />

    </f:form>

</f:section>

TextField Partial:

<f:form.textfield name="tx_survey_survey[answers][value][]" value="" />
<f:form.hidden name="tx_survey_survey[answers][qid][]" value="2" />

SessionController:

<?php
namespace Stupro\Survey\Controller;
/**
 *
 *
 * @package survey
*
*/
class SessionController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
    
    /**
     * sessionRepository
     *
     * @var \Stupro\Survey\Domain\Repository\SessionRepository
     * @inject
     */
    protected $sessionRepository;
    
(...)

    /**
     * Creates a new session
     *
     * @param Stupro\Survey\Domain\Model\Survey $survey The survey the session belongs to
     * @param Stupro\Survey\Domain\Model\Session $newSession A fresh session object which has not yet been added to the repository
     * @param array $answers An array of answers. array(amount => '12.50', comment => 'Children')
     * @return void
     * @dontverifyrequesthash
     */
    public function createAction(Stupro\Survey\Domain\Model\Survey $survey, \Stupro\Survey\Domain\Model\Session $newSession, array $answers = array()) {

//         $newSession = $this->createAndAddAnswers($newSession, $answers);
        $newSession->setSurvey($survey);
        
        $survey->addSession($newSession);
        $this->sessionRepository->add($newSession);
        
        $this->redirect('list', 'Session');
    }

    /**
     * Creates an answer for every item in the answers array and adds it to the session.
     *
     * @param Stupro\Survey\Domain\Model\Session $session The sessions the answers should be added to
     * @param array $answers An array of answers. array(amount => '12.50', comment => 'Children')
     * @return Stupro\Survey\Domain\Model\Session The Session
     */
    protected function createAndAddAnswers(Stupro\Survey\Domain\Model\Session $session, array $answers = array()) {
        foreach ($answers['value'] as $key => $value) {
            if (!empty($value)) {
                $session->addAnswer(new Stupro\Survey\Domain\Model\Answer($value, $answers['qid'][$key]));
            }
        }
        return $session;
    }

}
?>

Ich bin für jegliche Hilfe, bzw. jeden neuen Ansatz sehr dankbar!

Gruß
BjoernBoba

harald1972 ·

Hallo,
also ich beziehe mich mal nur auf den 2. Post.
Mir ist auch nicht ganz klar, was du willst oder vorhast, aber sei's drum 😉

Ich sehe z.B. keinen Zusammenhang zwischen dem Aufruf <f:render partial ...
und dem Partial-Zweizeiler darunter.
Hier übergibst du Variablen type, question und options. Dort sehe ich keine davon. o.O
Dann sehe ich, daß die beiden Felder für je ein Array stehen, wegen den leeren [] Klammern.
In der createAndAddAnswers() gehst du auf diesen Punkt ein. Obwohl diese in der CreateAction auskommentiert ist. Aber bei der Funktion steig ich grad eh nicht durch :o

Wenn sonst alles richtig ist, sollte übrigens

$newSession->setSurvey($survey);

überflüssig sein, wegen

$survey->addSession($newSession);

Ebenfalls redundant ist die Angabe des 'Session'-Controllers in der redirect-Anweisung, wenn du dich eh schon im SessionController befindest.

Wie sieht eigentlich die newAction aus?
Oha, ich sehe grad, daß das die showAction sein soll, mit der du die create aufrufst. Nun, machbar ist das schon. Gut, wie sieht dann die showAction aus?

BjoernBoba ·

Habe eben erst gesehen, dass ich ne Antwort bekommen habe. Hatte schon fast nicht mehr damit gerechnet 😉
Aber jedenfalls vielen Dank schonmal 🙂

Also ich fang mal an auf deine Fragen einzugehen:
Also nochmal allgemein, ich möchte innerhalb eines Formulars mehrere Objekte der Klasse "Answer" erstellt werden und für jedes Objekt die Variable "value" gefüllt werden.
Um dies zu lösen bin ich auf die Vorgehensweise, die anscheinend funktioniert, in folgendem Thread in diesem Forum gestoßen:
#106852
Allerdings habe ich es noch nicht lauffähig geschafft diese Lösung an meine Extension anzupassen...
Hast du dir diesen Thread angeschaut?

Zu den Partials:
Es gibt natürlich verschiedene, je nachdem welcher Fragetyp im Backend beim Erstellen einer Frage ausgewählt wird.
Als Beispiel mal das Partial für eine Frage mit mehreren Antwortmöglichkeiten und nur einer möglichen Antwort (RadioButtons):
Hier werden dann auch die übergebenen Argumente genutzt.

{namespace vh=Tx_survey_ViewHelpers}

<f:for each="{options}" as="option">
	<f:form.radio value="{option.value}" name="{question.uid}" />{option.value} 
				<br />
</f:for>

Dann noch zu dem Punkt, dass in der createAction der Aufruf der createAndAddAction auskommentiert ist:
Das war lediglich ein Fehler meinerseits beim Erstellen des Posts. Das tut mir Leid. Die Zeile soll natürlich nicht auskommentiert sein.

Mit der Redundanz das kann natürlich stimmen, daran sollte es allerdings nicht liegen, dass es noch nicht funktioniert.

Die showAction ist die eines anderen Controllers, die des SurveyControllers, da ja ein Survey, also eine Umfrage angezeigt wird und dafür eine Session mit Answers erstellt werden.
Dies Action ist allerdings wenig spektakulär:

	public function showAction(\Stupro\Survey\Domain\Model\Survey $survey) {
		$newSession = $this->objectManager->create('Stupro\\Survey\\Domain\\Model\\Session');

		$this->view->assign('newSession', $newSession);
		$this->view->assign('survey', $survey);
	}

Vielleicht siehst du, oder auch jemand anderes, ja irgendwo einen Fehler, oder zumindest einen Punkt woran es liegen könnte. Denn ich bin eigtl. der Meinung, dass ich alles gleichermaßen wie bei sjr_offers übernommen habe.
Ich bin für jede erdenkliche Hilfe sehr dankbar!

Mit freundlichen Grüßen
BjoernBoba

harald1972 ·

Okay, ich sehe 2 Dinge.

Wie in dem anderen thread steht, liegt der Schlüssel wohl im Name-Parameter. Das kann man aber so und so sehen.

Mir ist die Namespace-Schreibweise noch nicht ganz geläufig, darum weiß ich nicht, ob führende Backslashes etwas ausmachen.

public function createAction(Stupro\Survey\Domain\Model\Survey $survey, \Stupro\Survey\Domain\Model\Session $newSession, array $answers = array()) {

Allerdings vermisse ich das "Stupro" in deinem Name-Parameter.

Unbekannter Benutzer ·

Führender Backslash ist zwingend. Das ist ein bisschen wie bei einem Dateipfad, mit führendem Backslash ist es ein absoluter Namespace, ohne wird es relativ ausgewertet, was eigentlich nie das gewünschte ist.

BjoernBoba ·

Du hast recht, dass der name Parameter im Falle von den RadioButtons nicht komplett ist. Aber den hab ich ja nur gepostet um deine vorherige Frage zu beantworten.
Ich teste momentan ausschließlich mit dem TextField Partial.
Und da sollte der Name-Parameter richtig sein.
Nochmal zur Erinnerung:

<f:form.textfield name="tx_survey_survey[answers][value][]" value="" />
<f:form.hidden name="tx_survey_survey[answers][qid][]" value="2" />

@Kitsunet:
Hast du vllt. noch irgend ne andere Idee wie das ganze funktionieren könnte?
Oder vllt wo mein Fehler liegen könnte?
Du kennst dich ja insgesamt sehr gut aus. Vllt hattest du ja schonmal mit so etwas zu tun.

Und ich bin schon fast am verzweifeln 🙁

Gruß
BjoernBoba

Unbekannter Benutzer ·

Mmm, ich würde das insgesamt ganz anders angehen, deshalb kann ich die Einzelfrage nicht sooo gut beantworten.

Ich würde in meiner action nur ein session object erwarten als Argument. Dem würde ich in einem hidden Field die survey setzen, damit braucht die survey schon mal nicht mehr übergeben werden.

Die answers würde ich auch direkt im Objekt bearbeiten, also dein Field müsste dann ungefähr so aussehen:

<f:form.textfield property="answers.0.value" />
<f:form.hidden property="answers.0.qid" value="2" />

Dann müssen die answers auch nicht mehr gesondert übergeben werden. Die 0 dann jeweils durch den aktuellen Schleifendurchlauf ersetzen.

Ich verstehe auch nicht warum die Answer die qid (question uid denk ich mal) speichert und nicht direkt eine Relation zum Question Objekt?

Außerdem natülrich sicherstellen, dass die Action auch wirklich aufgerufen wird wenn du das Form abschickst.

Viele Grüße
Christian

BjoernBoba ·

Schonmal Danke für deine Antwort.

Ich komme erst am Wochenende dazu etwas zu machen.
Ich gebe dann spätestens am Montag ein neues Feedback, ob ich irgendwie weiter gekommen bin.

Vielleicht klappt es im Zuge dessen dann ja 🙂

Gruß
BjoernBoba

BjoernBoba ·

Hey,

Also ich habe jetzt mal verscuht deine Tipps umzusetzen.
Erstmal wird jetzt die "New"Action von Session angezeigt und nicht mehr die "Show" von Survey, das ganze scheint etwas intuitiver.
Allerdings muss ich dabei dann ja immer noch das Survey mit übergeben, um es an die Session binden zu können.

Das mit dem Field habe ich dann auch so übernommen.

Das mit der qid stimmt, da fehlt noch eine Relation. Allerdings bleibt das Problem, dass beim Drücken des Submit Buttons nichts passiert, außer das die View erneut mit leeren Feldern geladen wird.

Gruß
BjoernBoba

PS: Ich hab dir mal eine PM geschrieben