I'm trying to perform validation in the login page for the name,email and password fields. If the input fails validation,the error message should be displayed.
But here,when I fill in the details and submit, it is redirected to the next page. Only the value is not saved in the database.
Why is the message not displayed?
This is my model:
class User extends AppModel {
var $name = 'User';
var $validate = array(
'name' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
'between' => array(
'rule' => array('between', 5, 15),
'message' => 'Between 5 to 15 characters'
)
),
'password' => array(
'rule' => array('minLength', '8'),
'message' => 'Mimimum 8 characters long'
),
'email_id' => 'email'
);
function loginUser($data) {
$this->data['User']['email_id'] = $data['User']['email_id'];
$this->data['User']['password'] = $data['User']['password'];
$login = $this->find('all');
foreach ($login as $form):
if ($this->data['User']['email_id'] == $form['User']['email_id'] && $this->data['User']['password'] == $form['User']['password']) {
$this->data['User']['id'] = $this->find('all',
array(
'fields' => array('User.id'),
'conditions' => array(
'User.email_id' => $this->data['User']['email_id'],
'User.password'=>$this->data['User']['password']
)
)
);
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
endforeach;
}
function registerUser($data) {
if (!empty($data)) {
$this->data['User']['name'] = $data['User']['name'];
$this->data['User']['email_id'] = $data['User']['email_id'];
$this->data['User']['password'] = $data['User']['password'];
if($this->save($this->data)) {
$this->data['User']['id']= $this->find('all', array(
'fields' => array('User.id'),
'order' => 'User.id DESC'
));
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
}
}
}
This is my controller:
class UsersController extends AppController {
var $name = 'Users';
var $uses=array('Form','User','Attribute','Result');
var $helpers=array('Html','Ajax','Javascript','Form');
function login() {
$userId = $this->User->loginUser($this->data);
if($userId>0) {
$this->Session->setFlash('Login Successful.');
$this->redirect('/forms/homepage/'.$userId);
break;
} else {
$this->flash('Login Unsuccessful.','/forms');
}
}
function register() {
$userId=$this->User->registerUser($this->data);
$this->Session->setFlash('You have been registered.');
$this->redirect('/forms/homepage/'.$userId);
}
}
EDIT
Why is the message,example,"Minimum 8 characters long", is not being displayed when give less than 8 characters in the password field?
<!--My view file File: /app/views/forms/index.ctp -->
<?php
echo $javascript->link('prototype.js');
echo $javascript->link('scriptaculous.js');
echo $html->css('main.css');
?>
<div id="appTitle">
<h2> formBuildr </h2>
</div>
<div id="register">
<h3>Register</h3>
<?php
echo $form->create('User',array('action'=>'register'));
echo $form->input('User.name');
echo $form->error('User.name','Name not found');
echo $form->input('User.email_id');
echo $form->error('User.email_id','Email does not match');
echo $form->input('User.password');
echo $form->end('Register');
?>
</div>
<div id="login">
<h3>Login</h3>
<?php
echo $form->create('User',array('action'=>'login'));
echo $form->input('User.email_id');
echo $form->input('User.password');
echo $form->end('Login');
?>
</div>
Your validation seems correct
How about trying the following:
Make sure set your $form->create to the appropriate function
Make sure there is no $this->Model->read() before issuing Model->save();
Edit
Did you have the following?:
function register()
{
//do not put any $this->User->read or find() here or before saving pls.
if ($this->User->save($this->data))
{
//...
}
}
Edit2
IF you're doing a read() or find() before saving the Model then that will reset the fields. You should be passing the variable as type=hidden in the form. I hope i am making sense.
Edit3
I think you need to move your registerUser() into your controller because having that function in the model doesn't provide you a false return. it's always going to be true even if it has validation errors.
Comment out the redirect line and set the debug to 2 in config/core.php. Then look at the sql that is being generated to see if your insert is working. If the errors are not being displayed, maybe in the view, you are using $form->text or $form->select instead of the $form->input functions. Only the $form->input functions will automatically display the error messages.
Related
In my Yii application, Yii's default Ajax is not working. Also default Ajax validation is not working. Has this been an installation problem or any other problem. How to enable Yii's default Ajax.
In my controller,
public function actionCreate() {
$model = new Company;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if (isset($_POST['Company'])) {
$company = Company::model()->findAll();
if (count($company) === 0) {
$model->attributes = $_POST['Company'];
$uploadedFile = CUploadedFile::getInstance($model, 'logo');
if (isset($uploadedFile)) {
$fileName = date('Ymdhis') . '_' . $uploadedFile->name; // $timestamp + file name
$model->logo = $fileName;
}
if ($model->validate()) {
if ($model->save()) {
if (isset($uploadedFile)) {
$uploadedFile->saveAs(Yii::app()->basePath . '/../banner/' . $fileName);
}
$this->redirect(array('create'));
}
}
} else {
Yii::app()->user->setFlash('error', 'Company details is already exists.');
}
}
$this->render('create', array(
'model' => $model,
));
}
In view page,
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'company-form',
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnChange' => true,
'validateOnSubmit' => true,
),
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation' => true,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
?>
<div class="form-group">
<?php echo $form->label($model, 'company_name', array('class' => 'req')); ?>
<?php echo $form->textField($model, 'company_name', array('class' => 'form-control')); ?>
<?php echo $form->error($model, 'company_name', array('class' => 'school_val_error')); ?>
</div>
Please help me.
Thanks...
Yii has no default AJAX. This is a technology based on JavaScript language. By default Yii includes a jQuery library which provided some methods for easy manipulations with AJAX. If you want use it on your page, you should add this string:
Yii::app()->clientScript->registerCoreScript('jquery');
You can add this string to your main layout, for example into top of /views/layouts/main.php`
I have model with below rules
public function rules()
{
return [
['student_dob',
function ($attr) {
$curr_date = date('d-m-Y');
if(empty($this->student_adm_date)) {
//$this->addError('student_dob',"Select Admission date first");
return true;
}
else {
$dob = date('Y-m-d',strtotime($this->$attr));
$adm = date('Y-m-d',strtotime($this->student_adm_date));
$diff = $adm-$dob;
if($diff <= 14) {
$this->addError('student_dob', "Birth date must be less than Admission date.");
return false;
}
else
return true;
}
},
]
];
}
This rule works good but error message don't appear on view page and my form view is below
<?php $form = ActiveForm::begin([
'layout' => 'horizontal',
'fieldConfig' => [
'template' => "{label}\n{beginWrapper}\n{input}\n{error}\n{endWrapper}",
'horizontalCssClasses' => [
'label' => 'col-sm-4',
'offset' => 'col-sm-offset-4',
'wrapper' => 'col-sm-8',
'error' => '',
'hint' => '',
],
],
]);
?>
<div class="row-left">
<?= $form->field($info, 'student_dob', ['template' => "{label} {input} <span class='status'> </span> {error}"])->widget(yii\jui\DatePicker::className(),
[
'model'=>$info,
'attribute'=>'student_dob',
'value'=>'',
'clientOptions' =>[
'dateFormat' => 'dd-mm-yyyy',
'changeMonth'=> true,
'changeYear'=> true,
'autoSize'=>true,
'showOn'=> "button",
'yearRange'=>'1900:'.(date('Y')+1),
'buttonImage'=> Yii::$app->homeUrl."images/calendar.png",
'htmlOptions'=>[
'style'=>'width:250px;',
'class'=>'form-control',
]]]); ?>
</div>
<?php ActiveForm::end(); ?>
I want to compare student_dob and student_adm_date with student_dob < student_adm_date rule validation, also error appear on form view page.
Solution
Just remove horizontalCssClasses and change template value like,
<?php $form = ActiveForm::begin([
'layout' => 'horizontal',
'fieldConfig' => [
'template' => "{label}\n{input}\n{error}",
],
]);
?>
You are subtracting one sting from another, I am not sure that works
$diff = $adm - $dob;
Try
if(strtotime($this->$attr) <= strtotime($this->student_adm_date))
Or change it to calcualte 14 days... altough not sure what you can register somebody 14 days after their birth.
You can calculate
if(strtotime($this->$attr) - strtotime($this->student_adm_date) > 60 * 60 * 24 * 14)
One more thing, in the validation functions you do not need return false; or return true; Try removing these, I personally do not know if they do anything.
I make a cgridview with one column editable for update data, based on this post.
With only a button (update licencias) to update all the fields in an ajax call.
But it only updates the first field.
I think that something is happened on $_POST variable.
I try several ways to look looping the $_POST variable unsuccessfully.
My code:
View:
<?php $form=$this->beginWidget('CActiveForm', array(
'enableAjaxValidation'=>true,
)); ?>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'rta-client-grid',
'selectableRows'=>1,
'selectionChanged'=>'mostrarDetalles', // via 1: para mostrar detalles al seleccionar
'dataProvider'=>$modelClient->search(),
'filter'=>$modelClient,
'columns'=>array(
array(
'id'=>'autoId',
'class'=>'CCheckBoxColumn',
'selectableRows' => '50',
),
'oid',
'name',
'surname',
'id_country',
'nif',
//'CifDni',
array(
'name'=>'CifDni',
'type'=>'raw',
'value'=>'CHtml::textField("CifDni[$data->oid]",$data->CifDni,array("style"=>"width:80px;"))',
//
),
array(
'class'=>'CButtonColumn',
),
array(
'class'=>'CButtonColumn',
'template' => '{detallarClientes}',
'buttons' => array(
'detallarClientes'=>array(
'label'=>'ver',
'imageUrl'=>'images/demo1/view.png',
'click'=>'js:mostrarDetalles',
),
),
),
),
)); ?>
<script>
function reloadGrid(data) {
$.fn.yiiGridView.update('rta-client-grid');
}
</script>
<?php echo CHtml::ajaxSubmitButton('Filter',array('rtaClient/ajaxupdate'), array(),array("style"=>"display:none;")); ?>
<?php echo CHtml::ajaxSubmitButton('Update licencias',array('rtaClient/ajaxupdate','act'=>'doUpdateLicencia'), array('success'=>'reloadGrid'),array("style"=>"float:right;")); ?>
<?php $this->endWidget(); ?>
Controller:
public function actionAjaxupdate()
{
$act = $_GET['act'];
if($act=='doUpdateLicencia')
{
$sortOrderAll = $_POST['CifDni'];
if(count($sortOrderAll)>0)
{
foreach($sortOrderAll as $menuId=>$sortOrder)
{
$model=$this->loadModel($menuId);
$model->CifDni = $sortOrder;
$model->save();
}
}
}
}
Post variable on FirebugConsole:
CifDni[10] H
CifDni[11] I
CifDni[12] J
CifDni[2] A
CifDni[3] B
CifDni[4] C
CifDni[6] D
CifDni[7] E
CifDni[8] F
CifDni[9] G
RtaClient[CifDni]
RtaClient[id_country]
RtaClient[name]
RtaClient[nif]
RtaClient[oid]
RtaClient[surname]
I Just solved the problem. I modified the controller adding:
foreach($_POST as $id=>$value)
{
if($id=="CifDni") {
foreach($value as $id2=>$value2)
{
$model=$this->loadModel($id2);
$model->CifDni = $value2;
$model->save();
}
}
}
But the problem in base was in other field (non showed on the grid) that has the rules 'required' and in the database has not value and they don't let me update by SQL error (the sql error don't appears in the log).
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
//array('pass', 'required'), //<----
$model->save(false);
To force save your model without validating through your rule instead of removing your rule on model.
I supposed the $form->addVlidator functions works as some front-end form checking thing, however when I add it, even the input is invalid, it seems the form is still being submited.
Or I was wrong, it's more a controller-side checking, which means the form will submit the data whatever then the server sides returns the error message?
My code works like this.
Form class:
<?php
class Application_Form_Test extends Zend_Form
{
public function init()
{
$this->setName('stdForm');
//$this->setMethod('post');
//$this->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'my-lovely-form'));
$this->setAttrib('enctype', 'multipart/form-data');
$this->setAction('somewhere')
->setMethod('post');
$username = $this->createElement('text', 'name', array('label' => 'Username:'));
$username->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]+/'))
->addValidator('stringLength', false, array(9, 20, 'messages'=>'Cannot be more than 9 chars'))
->setRequired(true)
->addFilter('StringToLower');
$email = $this->createElement('text', 'email', array('label' => 'E-mail'));
$email->addValidator('StringLength', false, array(8))
->setRequired(true);
$password = $this->createElement('password', 'pass1', array('label' => 'Password'));
$password->addValidator('StringLength', false, array(6))
->setRequired(true);
$password2 = $this->createElement('password', 'pass2', array('label' => 'Repeat password'));
$password2->addValidator('StringLength', false, array(6))
->setRequired(true);
$message = $this->createElement('textarea', 'message', array('label' => 'Message'));
$message->addValidator('StringLength', false, array(6))
->setRequired(true)
->setAttrib('COLS', '40')
->setAttrib('ROWS', '4');
$captcha = new Zend_Form_Element_Captcha('foo', array(
'label' => "human?",
'captcha' => 'Figlet',
'captchaOptions' => array(
'captcha' => 'Figlet',
'wordLen' => 6,
'timeout' => 300,
),
));
// Add elements to form:
$this->addElement($username)
->addElement($email)
->addElement($password)
->addElement($password2)
->addElement($message)
->addElement($captcha)
// use addElement() as a factory to create 'Login' button:
->addElement('submit', 'send', array('label' => 'Form sender'));
}
}
Controller code:
public function aboutAction()
{
$this ->_helper->layout->disableLayout();
$form = new Application_Form_Test();
$this->view->testForm = $form;
}
View file:
<?php echo $this->testForm;?>
The second: "the form will submit the data whatever then the server sides returns the error message". In order to do this you must call $form->isValid($this->_request->getPost()) in your action.
If it is not valid then you need to send data back to the user:
$form->populate($this->_request->getPost());
$this->view->form = $form;
For client side validation you can use http://docs.jquery.com/Plugins/Validation
let's say I have a blog with a module "post".
now I display a post like this: post/index?id=1
in the index-action i generate a new CommentForm and pass it as $this->form to the template and it is being displayed at the bottom of a post (it's just a textfield, nothing special). form action is set to "post/addcomment". How can I display the validation errors in this form? using setTemplate('index') doesn't work because I would have to pass the id=1 to it...
thanks
UPDATE:
here's a sample code:
public function executeIndex(sfWebRequest $request)
{
$post = Doctrine::getTable('Posts')->find($request->getParameter('id'));
$this->post = $post->getContent();
$comments = $post->getComment();
if ($comments->count() > 0)
$this->comments = $comments;
$this->form = new CommentForm();
$this->form->setDefault('pid', $post->getPrimaryKey());
}
public function executeAddComment(sfWebRequest $request) {
$this->form = new CommentForm();
if ($request->isMethod('post') && $request->hasParameter('comment')) {
$this->form->bind($request->getParameter('comment'));
if ($this->form->isValid()) {
$comment = new Comment();
$comment->setPostId($this->form->getValue('pid'));
$comment->setComment($this->form->getValue('comment'));
$comment->save();
$this->redirect('show/index?id='.$comment->getPostId());
}
}
}
and my Comment Form:
class CommentForm extends BaseForm {
public function configure() {
$this->setWidgets(array(
'comment' => new sfWidgetFormTextarea(),
'pid' => new sfWidgetFormInputHidden()
));
$this->widgetSchema->setNameFormat('comment[%s]');
$this->setValidators(array(
'comment' => new sfValidatorString(
array(
'required' => true,
'min_length' => 5
),
array(
'required' => 'The comment field is required.',
'min_length' => 'The message "%value%" is too short. It must be of %min_length% characters at least.'
)),
'pid' => new sfValidatorNumber(
array(
'required' => true,
'min' => 1,
'max' => 4294967295
),
array(
'required' => 'Some fields are missing.'
))
));
}
}
and finally, indexSuccess:
<?php echo $post; ?>
//show comments (skipped)
<h3>Add a comment</h3>
<form action="<?php echo url_for('show/addComment') ?>" method="POST">
<table>
<?php echo $form ?>
<tr>
<td colspan="2">
<input type="submit" />
</td>
</tr>
</table>
</form>
that's it.
If you're using sf 1.4 just put executeAddComments and executeIndex together in one function (executeIndex for example) and you'll be fine. setTemplate won't work here.
Are you using the handleError method in the action ? The id=1 part of your url should not change if inside the handleError method, you do a return sfView::SUCCESS;
UPDATE:
It actually changes, what you need to do is submit the id along with the comment [Which I'm sure you're already doing because a comment that doesn't refer to a post doesn't make much sense], then in your handleError method, instantiate the post object there.
Try to change your form action to
<?php echo url_for('show/addComment?id=' . $post->getId()) ?>
Doing this, your post id parameter should be available even on your post request, and it should work with setTemplate('index') or forward at the end of executeAddComment