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)
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)
Related
Controller has index() method and display() method.
Method index displays the image. and this method called display() doesn't display the images.
Both methods are in same controller.
Both methods are calling the same view file called
$this->load->view('home/portfolio2');
.
index() method is displaying the image but display() method not displaying the image.
index method code is
public function index() { //$this->load->view('images/homeimage'); //home image.
$this->load->view('home/portfolio2');
$this->load->view('home/header');
$this->load->view('home/viewcategory');
$result['msg'] = $this->W_model->latestupdates();
$result['title'] = 'latest updated';
if($result['msg'] == NULL) {
echo "check for albums in DB";
}else{
$this->load->view('home/latestsongsupdated', $result);
}
$this->load->view('home/footer');
}
display method code is
Public function displayalbums($albums, $lang){
$result['title'] = $lang;
$result['msg'] = $this->W_model->displayalbum($albums);
if($result['msg'] == NULL) { ?>
<h3 style = "margin-left: 20px;">
<?php echo "Songs will be updated soon, Please check for other songs"; ?>
</h3> <?php
} else{
$this->load->view('home/portfolio2');
$this->load->view('home/viewcategory');
$this->load->view('home/albums', $result);
}
}
Any advise, help will be more appreciated.
The correct syntax for image src is:
<?php echo base_url('assets/images/glow_in_worship_by_riyovincent-d571aon.jpg'); ?>
If that does not work echo base_url() somewhere. It should point to localhost/worship if your entire CI is in an htdocs or HTML subfolder that's called workshop. If it doesn't then you should edit your base_url correctly in the config as http://localhost/workship.
You can also use the image helper to generate the image tag (load HTML helper):
<?php echo img('assets/images/glow_in_worship_by_riyovincent-d571aon.jpg'); ?>
Note: this method also requires the base_url to be set correctly.
#raviraj123456
Use the full URL like this: 'http://www.example.com/assets/images/…; in src of the img tag and it will work.
I'm dissatisfied with the way Zend_Form renders form elements by default, and want to override it for all forms produced by instantiating a helper class I have that inherits from Zend_Form to take care of some things that I do on all of my forms.
The changes I want to make seem more complicated than is reasonable/possible with decorators, so I'd like to use a custom HTML template to accomplish this, where I get to plug form values into a custom HTML snippet.
How can I set all HTML elements rendered by my class to use an HTML template? And what properties/functions should I call from the template to get the stuff Zend_Form renders by default? Lastly, I would prefer to do this without having to manually set the template on each input element I create in my code.
You can extend the defualt Zend_Form class with your own Custom_Form class. In the init() method overwrite the default element decorators. Here my code snippet:
//class Custom_Form extends Zend_Form
public function init()
{
$this->setElementDecorators(
array(array('ViewScript', array('viewScript' => '/controller_name/forms/fields/input-text.phtml'))),
array('email', 'firstname', 'lastname')
);
}
I've done my share of coding with ZF1 and the best way I found to render nice forms was to use Twitter Bootstrap along with it.
Check the following links to see if that's also a satisfactory solution for you too:
how to use the twitter bootstrap framework in a zend framework 1 application?
http://twitter.github.io/bootstrap/
I wound up using a custom viewscript that I genericized to work with arbitrary forms.
Using this approach, I was able to do the following things:
Add an asterisk after the label of required form elements
Group inputs and errors together in one div, so that when I float the labels to the left things still line up
Add a special class to erroring inputs so I can highlight them
Change certain error messages to include the name of the element instead of "Value"
Pass a text note along with the form elements to be displayed under the input
Not wrap labels and inputs in special elements
Some of these things are impossible without a viewscript, and some are just a pain to implement. I think this solution will be much more flexible for me going forward.
In my helper class' render() function:
$view = new Zend_View();
$view->setBasePath(SRC_ROOT . "/templates/forms");
$this->setDecorators(array(array('ViewScript', array('viewScript' => 'viewscript.php'))));
And here's my viewscript:
<link rel="stylesheet" type="text/css" href="/styles.css" />
<form id="<?php echo $this->element->html_id ?>" class="<?php echo $this->element->html_class ?>" enctype="application/x-www-form-urlencoded" action="" method="post">
<?php foreach($this->element as $element) { ?>
<?php
$decorators = $element->getDecorators();
if(isset($decorators["Zend_Form_Decorator_Label"])) {
$label = $element->getLabel();
} else {
$label = "";
}
if($element->isRequired() === true) {
$label .= " *";
}
?>
<label class="label" for="<?php echo $element->getName(); ?>"><?php echo $label; ?></label>
<div class="formInput">
<?php
// Add the error class to make the form inputs highlight in red
if($element->hasErrors()) {
$attribs = $element->getAttribs();
if(!isset($attribs["class"])) {
$attribs["class"] = "";
}
$attribs["class"] .= " inputError";
$element->setAttribs($attribs);
}
// Print the input using Zend_Form's own mechanisms
$element->setDecorators(array('ViewHelper')); // Removes all decorators (labels, etc.)
$v = new Zend_View();
$element->setView($v);
echo $element->render();
if(isset($element->note)) {
echo "<p>{$element->note}</p>";
}
// Print the error messages
if($element->hasErrors()) {
$errors = $element->getMessages();
?>
<ul class="errors <?php echo sizeof($errors) == 1 ? "noDecorations" : "" ?>">
<?php
foreach($errors as $error => $message) {
// Custom error messages
if($error === "isEmpty") {
$message = $element->getLabel() . " cannot be empty";
} ?>
<li><?php echo $message ?></li>
<?php } ?>
</ul>
<?php } ?>
</div>
<div style="float: clear;"></div>
<?php } ?>
</form>
I have a form and the submit button check if true or false.
If it's true redirect to another page.
If it's false stay on the same page and print the error message.
The error message is print out with a flash messenger.
But, in some case it doesn't print in the first try when submit is false, it always print out on the second click.
Did I did something wrong?
And also, is there a way to set difference flash messenger name? Because, on my others pages that have flash messenger, print out the error when page is refreshed.
Here's the code:
if(isset($_POST['submit'])) {
// code to inputfields
if(true) {
//redirect to some page
} else {
// print the flash error on the same page
$this->_helper->flashMessenger->addMessage(" This email is already taken");
$this->view->messages = $this->_helper->flashMessenger->getMessages();
}
}
HTML:
<center>
<div style="color:red">
<?php if (count($this->messages)) : ?>
<?php foreach ($this->messages as $message) : ?>
<div id="field_name">
<strong style="text-transform:capitalize;">Email </strong>
- <?php echo $this->escape($message); ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</center>
flashmessenger is really designed to be used on a redirect of some kind, so any message you see probably comes from the prior action's execution. Your current code would not flash any message during the first 'post'.
you may have some luck if you try something like:
public function init()
{
//This will catch any messege set in any action in this controller and send
//it to the view on the next request.
if ($this->_helper->FlashMessenger->hasMessages()) {
$this->view->messages = $this->_helper->FlashMessenger->getMessages();
}
}
public function someAction()
{
if(isset($_POST['submit'])) {
// code to inputfields
if(true) {
//redirect to some page
} else {
// print the flash error on the same page
$this->_helper->flashMessenger->addMessage(" This email is already taken");
//will redirect back to original url. May help, may not
$this->_redirect($this->getRequest()->getRequestUri());
}
}
}
Here's an action I coded that demonstrates what you seem to be attempting.
public function updatetrackAction()
{
//get the page number
$session = new Zend_Session_Namespace('page');
$id = $this->getRequest()->getParam('id');
//get the entity object
$model = new Music_Model_Mapper_Track();
$track = $model->findById($id);
//get the form
$form = new Admin_Form_Track();
$form->setAction('/admin/music/updatetrack/');
//test for 'post' 'valid' and update info
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$data = $form->getValues();
$newTrack = new Music_Model_Track($data);
$update = $model->saveTrack($newTrack);
//add message
$this->message->addMessage("Update of track '$update->title' complete!");
//redirects back to the same page number the request came from
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));
}
} else {
//if not post display current information
//populate() only accepts an array - no objects -
$form->populate($track->toArray());
$this->view->form = $form;
}
}
I am using Twitter Bootstrap to style validation_errors for a registration page:
<?php
echo "<div class='alert alert-error span4'>";
echo validation_errors();
echo "</div>";
?>
The validations work and show up but part of the styling is always present (the div tag has a red background). Is there a way to have the styling show up ONLY when the validation_errors are present. I have tried a few things (embedding html in php tags and enclosing the php in div tags) but the result is the same.
The reason that the div structure still appears is because it's echoing without regard to whether there are errors or not.
You could set the value of a variable to the result of your validation_errors() function in your Controller, then only display the alert div in your View if you've actually got an error...
Your controller would assign the variable to hold the (potential) error:
$this->data['reported_error'] = validation_errors();
$this->load->view('view_name', $this->data);
Then your view would only display the alert div if there was an error:
if ( isset($reported_error) )
{
echo "<div class='alert alert-error span4'>".$reported_error."</div>";
}
This requires your validation_errors function to only return a value if there is an error.
You can try something like this it works for me.
<?php if(validation_errors()):?>
<div class='alert alert-error span4'><?php echo validation_errors(); ?></div>
<?php endif;?>
I use the following construct to put the errors with special classes next to the fields that they reference:
<div class="<?php echo my_error_class('fieldname') ?>">
<input type="whatever" name="fieldname" />
<span class="whatever"><?php echo my_error_msg('fieldname') ?></>
</div>
with the following functions in a CI helper:
<?php
if ( ! function_exists('my_error_class')) {
function my_error_class($field, $error_class = "error") {
if (FALSE === ($OBJ =& _get_validation_object())){
return '';
}
if(isset($OBJ->_field_data[$field]['error']) && !empty($OBJ->_field_data[$field]['error'])) {
return $error_class;
}
else {
return '';
}
}
}
if ( ! function_exists('my_error_msg')) {
function my_error_msg($field,$default = '') {
if (FALSE === ($OBJ =& _get_validation_object())){
return $default;
}
if(isset($OBJ->_field_data[$field]['error']) && !empty($OBJ->_field_data[$field]['error'])) {
return $OBJ->_field_data[$field]['error'];
}
else {
return $default;
}
}
}
I was having the same issue. I assigned validation_errors() to a variable in my controller and passed it to the view.
Going off James' solution, I had to change:
if ( isset($reported_error) )
to:
if (!empty($reported_error))
Once I did this, the alert block only displayed when there was an error.
I didn't find this in the guide but apparently validation_errors takes two optional args for a prefix and suffix... so you can do:
validation_errors('<p class="text-warning">', '</p>');
I have a problem with displaying a view. When I pass var to view, view doesn't render.
Controller:
public function indexAction()
{
$branchModel = new Application_Model_Branches();
$branches = $branchModel->getAllBranches();
$this->view->menu = $branches;
}
View (index.phtml):
<h2>Menu</h2>
<?php
$this->htmlList($this->menu);
?>
When I try debug $branches without assign it to view, all seems to be ok, but when I try push it to view,index.phtml don't appear.
Regards
You're just missing an echo in your code, the htmlList view helper returns a value - it doesn't echo it. Some examples of the various form view helpers can be seen here
<h2>Menu</h2>
<?php
echo $this->htmlList($this->menu);
?>
controller
$this->view->variableName = "Hello World!";//assign here
$this->view->assign('variableName1', "Hello new World!");//assign here
view
echo $this->variableName;//echo here
echo $this->variableName1;//echo here