Question

I am building a test Lithium app to learn how it works and I found that the form helper doesn't seem to recognise my data being passed back or any validation errors.

At the moment I'm having to manually pass back my errors and then process them in the view.

QuestionsController::ask

public function ask() {
    if (!empty($this->request->data)) {
        $question = Questions::create($this->request->data);
        if ($question->save()) {
            return $this->redirect(array('Questions::view', 'args'=>$question->id));
        } else {
            $errors = $question->errors();
        }

        if (empty($question)) {
            $question = Questions::create();
        }

        return compact('question', 'errors');
    }
}

views/questions/ask.html.php

<?php
// Assign the protected object to a variable so we can get at it
if(isset($question)){
    $data = $question->data();
}else{
    $data['title'] = '';
    $data['text'] = '';
}
?>

<?=$this->form->create();?>

    <?=$this->form->field('title', array('placeholder'=>'Title your question', 'value'=>$data['title']));?>
    <?php if(isset($errors['title'])){
        echo "<div class='alert alert-error'><a class='close' data-dismiss='alert' href='#'>×</a>";
        foreach($errors['title'] as $e){
            echo $e."<br/>";
        }
        echo "</div>";
    }?>

    <?=$this->form->field('text', array('placeholder'=>'Enter your question (supports Markdown)', 'type'=>'textarea', 'value'=>$data['text']));?>
    <?php if(isset($errors['text'])){
        echo "<div class='alert alert-error'><a class='close' data-dismiss='alert' href='#'>×</a>";
        foreach($errors['text'] as $e){
            echo $e."<br/>";
        }
        echo "</div>";
    }?>
    <p>Text input supports <?php echo $this->html->link('markdown', 'http://en.wikipedia.org/wiki/Markdown');?></p>

    <?=$this->form->submit('Ask', array('class'=>'btn'));?>
<?=$this->form->end();?>

I can see from the lithium\template\helper\Form that the field() method can take a template parameter, which in the example is <li{:wrap}>{:label}{:input}{:error}</li> so there is capacity in the helper for displaying the validation messages.

So how do I organise my data in my controller so that it's passed back to the view in order for the helper to populate my fields and also display errors?

Edit
I should add that the example 'Sphere' app, also uses this method, so is it standard? (ref)

Was it helpful?

Solution

TL;DR

the short answer is that you can bind the form to a subclass of Entity, i.e. a Record or Document as shown in Form::create() (link is shortened as :: breaks the link parser).

your code would look like:

<?= $this->form->create($question); ?>
<?= $this->form->field('title'); ?>
<?= $this->form->field('text'); ?>

Long answer:

QuestionsController::ask():

public function ask() {
    $question = Questions::create();
    if (!empty($this->request->data)) {
        if ($question->save($this->request->data)) {
            return $this->redirect(array('Questions::view', 'args'=>$question->id));
        }
    }
    return compact('question');
}

views/questions/ask.html.php:

<?= $this->form->create($question); ?>

    <?= $this->form->field('title', array('placeholder'=>'Title your question'));?>

    <?= $this->form->field('text', array('placeholder'=>'Enter your question (supports Markdown)', 'type'=>'textarea'));?>

    <p>Text input supports <?php echo $this->html->link('markdown', 'http://en.wikipedia.org/wiki/Markdown');?></p>

    <?=$this->form->submit('Ask', array('class'=>'btn'));?>

<?=$this->form->end();?>

Note how the form helper will automatically display errors in case there are any :)

Some useful links into the #li3 philosophy:

1 - http://www.slideshare.net/nateabele/lithium-the-framework-for-people-who-hate-frameworks

2 - Video of roughly the same presentation (w/ a good example on changing form templates)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top