How can I wrap a fieldset tag around my form rows, and how can I add a has-danger class to the fieldset when an element fail to validate?
I think I need to create a viewhelper, check if a specific formelement has a validation message and wrap the row with a fieldset, but I'm not sure if that's the right approach or how to do it.
The output I want on validation error:
<fieldset class="has-danger"><label for="username">Username</label>
<input type="text" name="username" id="username" class="form-control
input-error" value="f"><ul><li>Needs to be 5-20 characters long</li>
</ul></fieldset>
register.phtml:
<?php
$form = $this->registerForm;
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formHidden($form->get('secret'));
echo $this->formRow($form->get('username'));
echo $this->formRow($form->get('password'));
echo $this->formRow($form->get('email'));
echo $this->formRow($form->get('confirm-email'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag($form);
Ok, you should use the formLabel(), formElement() and formElementErrors() view helpers instead of formRow().
To my ZF2 knowledge, the formRow() view helper doesn't let you have control on the HTML output easily. It displays the complete input HTML (label + input + errors) in one line of code.
To simply achieve your goal, your phtml structure for one input has to be as follow :
// NAME_OF_YOUR_FILE.phtml
<?php
$userNameInput = $form->get('username');
$userNameInputErrors = $this->formElementErrors($userNameInput);
?>
<fieldset class="<?= $userNameInputErrors ? 'has-danger' : '' ?>" >
<?= $this->formLabel($userNameInput) ?>
<?= $this->formElement($userNameInput) ?>
<?= $userNameInputErrors ?>
</fieldset>
This is a hard work to do this for each fields in form, so I suggest you to put this logic in a view helper.
// MyFormRow.php
<?php
namespace Your\Namespace;
use Zend\View\Helper\AbstractHelper;
class MyFormRow extends AbstractHelper
{
protected $formLabelViewHelper;
protected $formElementViewHelper;
protected $formElementErrorsViewHelper;
public function __construct($formLabelViewHelper, $formElementViewHelper, $formElementErrorsViewHelper)
{
$this->formLabelViewHelper = $formLabelViewHelper;
$this->formElementViewHelper = $formElementViewHelper;
$this->formElementErrorsViewHelper = $formElementErrorsViewHelper;
}
public function __invoke($formElement)
{
$html = '';
$errors = $this->formElementErrorsViewHelper->__invoke($formElement);
$html .= '<fieldset class=" . ($errors ? 'has-danger' : '') . ">';
$html .= $this->formLabelViewHelper->__invoke($formElement);
$html .= $this->formElementViewHelper->__invoke($formElement);
$html .= $errors;
$html .= '</fieldset>';
return $html;
}
}
?>
Declare it in your Module.php.
// In your Module.php
<?php
...
public function getViewHelperConfig()
{
return [
'factories' => [
'myFormRow' => function (HelperPluginManager $helperPluginManager) {
$formLabelViewHelper = $helperPluginManager->get('formLabel');
$formElementViewHelper = $helperPluginManager->get('formElement');
$formElementErrorsViewHelper = $helperPluginManager->get('formElementErrors');
return new MyFormRow($formLabelViewHelper, $formElementViewHelper, $formElementErrorsViewHelper);
},
],
];
}
?>
And now in your phtml file, simply :
// NAME_OF_YOUR_FILE.phtml
...
<?= echo $this->myFormRow($form->get('username')) ?>
...
Related
I'm totally new to Yii and I need help please even if it looks trivial. I have a page where I generate a table from my database, I added a search option and I need to generate the result as a table also.
The problem is that when I click the button nothing happens.
I also tried using submit but it didn't work.
This is my code:
...views/supermarkets/index.php:
<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
use app\views\supermarkets\search;
?>
<h1>Supermarkets</h1>
<ul>
<p>
Search by Name
</p>
<INPUT TYPE = "Text" VALUE ="" NAME = "searchname">
<button onclick="myFunction($_POST['searchname'])">Search</button>
<h3> </h3>
<?php
$array = (array) $supermarkets;
function myFunction($sname){
if (isset($sname) && $sname!='') {
$row = Yii::app()->db->createCommand(array(
'select' => '*',
'from' => 'supermarkets',
'where' => array('like', 'Name','%'.$sname.'')
))->queryRow();
$array = (array) $row;
}
echo $array;
$this->render('index',array('supermarkets' => $array));
}
function build_table($array){
// start table
$html = '<table class="altrowstable" id="alternatecolor">';
// header row
$html .= '<tr>';
foreach($array[0] as $key=>$value){
$html .= '<th>' . $key . '</th>';
}
$html .= '</tr>';
// data rows
foreach( $array as $key=>$value){
$html .= '<tr>';
foreach($value as $key2=>$value2){
$html .= '<td>' . $value2 . '</td>';
}
$html .= '</tr>';
}
// finish table and return it
$html .= '</table>';
return $html;
}
echo build_table($array);
?>
<?= LinkPager::widget(['pagination' => $pagination]) ?>
Even in the debug it doesn't pass through myFunction. Any suggestions please?
You should follow proper Yii syntax, ie define your function inside controller and call that function by creating button on index.php or other view file like:
Button on view file:
<?= Html::a('Search', ['search-function', 'Name' => $this->$sname], ['class' => 'btn btn-success']) ?>
And in your controller:
//As you define your function
public function actionSearchFunction($sname){
if (isset($sname) && $sname!='') {
$row = Yii::app()->db->createCommand(array(
'select' => '*',
'from' => 'supermarkets',
'where' => array('like', 'Name','%'.$sname.'')
))->queryAll();
$array = (array) $row;
I will explain you step by step. First, Note that everything inside <?php ?> tag will be generate at the server BEFORE rendering of the view. So, you can't execute php code on the client. If you need to execute some server code from client, You need to use Ajax(asynchronous JavaScript and XML). I recommend you to learn ajax, because this is very useful in web applications. OK, let's solve your problem. First step is to define an event for button click. You have myFunction already and I change it to this:
<button onclick="myFunction();">Search</button>
And I change your input to this:
<input type="text" value ="" name="searchname", id="searchname">
Now, I write myFunction() body in the <script></script> tag:
<script>
function myFunction()
{
$.ajax({
url: '<?php echo Yii::app()->baseUrl . '/supermarkets/sample' ?>',
type: 'post',
data: {searchname: $("#searchname").val()},
success: function (data) {
alert(data);
}
});
}
</script>
Now, you need to define an action in your controller for ajax request. I supposed you have SupermarketsController. Try to write actionSample() in it like this:
public function actionSample()
{
$array = (array) $supermarkets;
$sname = $_POST['searchname'];
...
echo "ok";
}
You can access the search input value in that function and all of your php code must be there. at the last line of that action, you must echo something(data or message). Everything you put after echo, you can get it as data parameter of success event of ajax request. In my example, you will see "ok" alert in your browser. I hope my explanation can help you to learn ajax. Note you need to include jquery library for using ajax. Good luck friend :)
I want to make text area in cactiveform in yii dynamically. but I am getting error i.e. "Property "Verse.translation" is not defined"
I have translation_text field, not translation field in my db. Secondly $trans['translation_text'] display the verse translation but when i keep it in textArea it is giving error. as i have described.
I have a code.
<?php foreach($model->verseTranslations as $trans) { ?>
<?php $model->translation = $trans['translation_text']; ?>
<?php echo $form->textArea($model,'translation',array('rows'=>6, 'cols'=>50)); ?>
<?php } ?>
But i do not know how to keep value $trans['translation_text'] in textArea.
Any help will be appreciated.
Thanks
Do it like this :
<?php foreach($model->verseTranslations as $trans) { ?>
<?php echo $form->textArea($model,'translation',array('value'=>$trans['translation_text'],'rows'=>6, 'cols'=>50)); ?>
<?php } ?>
And in your model as RobM said earlier, but don't forget to add a validator in you Verse class for 'translation' attribute ! :
class Verse extends CActiveRecord
{
public $translation;
public function rules()
{
return array(
array(
'translation',
'safe',
'on'=>'',
),
//others validators here
);
}
}
Just replace the second parameter in $form->textArea with $trans['translation_text'], so that it becomes:
<?php echo $form->textArea($model, $trans['translation_text'], array('rows'=>6, 'cols'=>50)); ?>
The second parameter is the value of the textArea, so the value of any variable here will show up as the default value of the text area element.
Add translation property to Verse class in models
class Verse extends CActiveRecord
{
public $translation;
controller
userdetails.php
class Controller_Userdetails extends Controller {
public function action_index() {
$view = new View('userdetails/index');
$this->response->body($view);
}
public function action_add() {//load adddetails.php
$userdetails = new Model_Userdetails();
$view = new View('userdetails/adddetails');
$view->set("userdetails", $userdetails);
$this->response->body($view);
}
public function action_post() {//save the post data
$userdetails_id = $this->request->param('id');
$userdetails = new Model_Userdetails($userdetails_id);
$userdetails->values($_POST);
$userdetails->save();
$this->request->redirect('index.php/userdetails');
}
}
views
adddetails.php
<?php echo Form::open('userdetails/post/'.$userdetails->id); ?>
<?php echo Form::label("first_name", "First Name"); ?>
<?php echo Form::input("first_name", $userdetails->first_name); ?>
<br />
<?php echo Form::label("last_name", "Last Name"); ?>
<?php echo Form::input("last_name", $userdetails->last_name); ?>
<br />
<?php echo Form::label("email", "Email"); ?>
<?php echo Form::input("email", $userdetails->email); ?>
<br />
<?php echo Form::submit("submit", "Submit"); ?>
<?php echo Form::close(); ?>
I am trying to insert the data into database.The name and email field are loading correctly,if i enter values and hit enter it is redirecting to other page but objects not saved in database.Need help to solve this.
I sometimes find problems in saving while using
$userdetails->values($_POST);
try using
$userdetails->first_name = $this->request->post('first_name');
$userdetails->last_name= $this->request->post('last_name');
$userdetails->email= $this->request->post('email');
Assuming the model is an ORM model (class Model_Userdetails extends ORM {}), you should use ORM::factory() to load the model. Furthermore it's recommended to use the expected parameter to be sure only the values you want to be inserted are used.
$user_details = ORM::factory('Userdetails');
$user_details->values($this->request->post(),
array('first_name', 'last_name', 'email')
);
$user_details->save();
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>
How to Validation Zend Form ? (opening tag)
Example :
Form :
class MyForm extends Zend_Form {
function init() {
$this->addElement('select','my_select',array(
'label'=>'My select :',
'required'=>true,
'multioptions'=>array(''=>'-select please-','1'=>'value1','2'=>'value2')
'validators'=>array(
array('NotEmpty', true, array('messages' => 'This field is required'))),
));
} }
Controller :
$form = new MyForm();
if ($this->_request->isPost()) {
$form_name=$this->getRequest()->getParams();
if($form->isValid($form_name)){
echo "==success==";
}
else{
echo "==no success==";
}
}
$this->view->form = $form;
View :
// Render the form opening tag
echo $this->form->renderForm(false);
echo '<table>';
echo '<tr>';
echo '<th>'
// Render the label
echo $this->form->my_select->renderLabel();
echo '</th>
echo '<td>';
// Render the select
echo $this->form->my_select->renderViewHelper();
echo $this->form->my_select->renderErrors();
echo '</td>';
echo '</tr>';
echo '</table>';
echo '</form>';
i want to show message validation at view
This code is complete in answer 18/02/2011
You can render errors on a specific element with:
echo $this->form->my_select->renderErrors();
If you want to render the errors for all the form in one place :
$form->addDecorator('FormErrors');
echo $form->renderFormErrors();
I'm not really sure what you mean here but here's my best guess...
If you want to render the set of validation errors for the form and its elements in one place, try adding the FormErrors decorator to the form. See Zend_Form_Decorator_FormErrors
As for validation, simply add validators to the elements as normal.
to have validation errors you first need to add validators to your form element ,
$formElement = new Zend_Form_Element_Text('username');
$formElement->addValidator(new Zend_Validate_Alnum());
to get validation error messages do
$arrayOfErrors = $this->view->form->getMessages();