How to display cakephp 2.5.3 model validation message.By default it shows html 5 validation message - html

How to display the validation message which is defined in CakePHP model.When I submit the form , CakePHP model validation works.But validation message for input field is not displayed. It shows HTML 5 validation Message. I want to display CakePHP model validation message. I am using CakePHP 2.5.3
Following is my code block:
Controller:
$this->User->set($this->request->data);
if ($this->User->validates()) {
if ($this->User->save($this->request->data)) {
$Email->send();
$this->Session->setFlash(__('The user has been created'));
if ($this->Auth->login()) {
$this->Session->setFlash(__('Welcome, ' . $this->Auth->user('username')));
$this->redirect($this->Auth->redirectUrl());
}
} else {
$this->Session->setFlash(__('The user could not be created. Please, try again.'));
}
}
Model:
public $validate = array(
'username' => array(
'nonEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required',
'allowEmpty' => false
),
'unique' => array(
'rule' => array('isUniqueUsername'),
'message' => 'This username is already in use'
),
'alphaNumericDashUnderscore' => array(
'rule' => array('alphaNumericDashUnderscore'),
'message' => 'Username can only be letters, numbers and underscores'
),
)
View:
<div id="divfirstname" class="input text required">
<label for="UserFirstname">First Name <span style="color:#FF0000">*</span></label>
<?php echo $this->Form->text('firstname');?>
</div>
<div id="divlastname" class="input text required">
<label for="UserLastname">Last Name <span style="color:#FF0000">*</span></label>
<?php echo $this->Form->text('lastname');?>
</div>
<div class="input text required">
<label for="UserUsername">Username <span style="color:#FF0000">*</span></label>
<?php echo $this->Form->text('username');?>
</div>

You don't need to wrap the validation-block around your save call.
So this is enough:
if ($this->User->save($this->request->data)) {
$Email->send();
$this->Session->setFlash(__('The user has been created'));
if ($this->Auth->login()) {
$this->Session->setFlash(__('Welcome, ' . $this->Auth->user('username')));
$this->redirect($this->Auth->redirectUrl());
}
} else {
$this->Session->setFlash(__('The user could not be created. Please, try again.'));
}
CakePHP handles automatically the validation when Model->save() is called and displays the error under your input fields. So if $this->save fails because of a validation error, cakephp adds <div class="error-message">Message Text from your model validation array</div> under the right input field.

You are left with 2 options :
Either dont use validation rule in cakePHP which validates on Client side.
On DOM ready , call $("#formId").removeAttr('novalidate'); Like
$(document).ready(function(){
$("#formId").removeAttr('novalidate');
});

Related

Update form after ajax save

I want form data updated after ajax save. Cause if item was new (id - empty), it tries to create new one each time. Also there are back-end generated fields which are appears after save.
<?php $form = ActiveForm::begin([
'method' => 'post',
'action' => ['category/save', 'id' => $category ? $category->id : ''],
'enableClientValidation' => true,
// 'enableAjaxValidation' => false,
'validateOnChange' => false,
'validateOnBlur' => false,
'validateOnSubmit' => true,
'options' => [
'id' => 'customer-update',
'class' => 'ajax-submit',
],
'fieldConfig' => [
'template' => '<div class="row-content-col1">{label}</div><div class="row-content-col2">{input}{error}</div>'
]
]); ?>
.......
<?php echo $form->field($category, 'url')->textInput(['class' => 'ip', 'readonly' => true]); ?>
......
<?php $form->end(); ?>
Form field produce such html:
<div class="row-content-col1"><label class="control-label" for="category-url">Url</label></div><div class="row-content-col2"><input type="text" id="category-url" class="ip" name="Category[url]" readonly><div class="help-block"></div></div>
</div>
And than on controller i return this (tried different variations):
{"error":false,"message":"Category 'asdfzsdf sdf' saved","data":{"name":"asdfzsdf sdf","url":"asdfzsdf-sdf","project_id":1,"id":21}}
What is valid response for ajax form? Or is there other way to handle this all ?
Pjax is really useful for your challenge, Just add your form inside of Pjax widget. add form action to new path(such: site/control-data).
In your action method do what you want, but send response like that :
return $this->renderAjax('form path',$model);
It's the general of what you must do.
But maybe you have problem with jquery or pjax or need some more data, but all questions have an answer,
See Pjax for ActiveForm

How can I display required fields error (validation) message with symfony formbuilder?

PagesController.php
$id = $request->request->get('id');
$target = $request->request->get('target');
$EntityName = 'App\\Entity\\' . ucwords($slug);
$em = $this->getDoctrine()->getManager();
$cmf = $em->getMetadataFactory();
$classes = $cmf->getMetadataFor($EntityName);
if($request->request->get('target')){
$item = new $EntityName();
$item= $this->getDoctrine()->getRepository($EntityName)->find($id);
$formBuilder = $this->createFormBuilder($item);
foreach ($classes->fieldMappings as $fieldMapping) {
$formBuilder->add($fieldMapping['fieldName'], TextType::class, array('attr' => array('class' => 'form-control'), 'required' => true,));
}
$formBuilder->add('cancel', ButtonType::class, array('label' => 'Cancel','attr' => array('class' => 'cancel form-btn btn btn-default pull-right close_sidebar close_h')))
->add('save', SubmitType::class, array('label' => 'Save','attr' => array('id' => 'submit-my-beautiful-form','class' => 'form-btn btn btn-info pull-right','style' => 'margin-right:5px')));
$form = $formBuilder->getForm();
$form->handleRequest($request);
$response = new JsonResponse(
array(
'message' => 'Success',
'output' => $this->renderView('form.html.twig',
array(
'target' => $target,
'entity' => $item,
'form' => $form->createView(),
))), 200);
return $response;
} else {
$em = $this->getDoctrine()->getManager();
foreach ($classes->fieldMappings as $fieldMapping) {
$func = 'set'.$fieldMapping['fieldName'];
$args = $data['form['.$fieldMapping['fieldName'].']'];
$entity->$func($args);
}
$em->persist($entity);
$em->flush();
$response = new JsonResponse(array('id' => $data['form[id]']), 200);
return $response;
}
form.html.twig
<section class="content-header" style="margin-bottom:20px">
<h1 style="float:left;margin-bottom:30px">Create Entry </h1>
</section>
<section class="content" style="clear:left">
<div class="form-group">
{{ form_start(form) }}
{{ form_end(form) }}
</section>
My form is working well, when I fill it out and press the "Save" Button it is stored in the database.
When I leave all fields empty and press "Save" nothing is happening and I get a 500 Error
An exception occurred while executing 'INSERT INTO members (username,
password, email, is_active) VALUES (?, ?, ?, ?)' with params ["",
null, "", "1"]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column
'password' cannot be null
This is actually fine, because the fields are required, but the errors are not displayed in my form, even if I added "required" = "true".
So when using the form builder, you have access to:
$form->isSubmitted()
and
$form->isValid()
As a result you can do something like:
if ($form->isSubmitted() && $form->isValid()) {
// save to database
}
We want to check the form is submitted before we check it's valid as if the form isn't submitted, it's unnecessary to check it's valid as it will be false.
This is going to prevent your MySQL error because your form technically isn't valid and you're trying to flush invalid data. We obviously only want to save our data when it's valid.
Of course, if the form fails you can return the view and in the template, you have access to
{{ form_errors() }}
This will probably cover what you need but you could also pass to your template something like
'formHasErrors' => $form->isSubmitted() && !$form->isValid(),
and then in your template
{% if formHasErrors %}
Something else you may want to do, this allows you to have more control over your fields, is separate out the field out like below:
{{ form_start(form) }}
{{ form_label(form.name) }}
{{ form_errors(form.name, {'attr': {'class': 'form-input'}}) }}
{{ form_widget(form.name) }}
{{ form_end(form) }}
It is very important you catch errors and handle them correctly. Your implementation didn't verify the form is valid which is why you were getting 500 errors.

how to handle multiple submit buttons in form cakephp3

I have just started learning cakephp3, so please excuse me for anything wrong.
So I have one form in which I am collecting data, I want to have two submit buttons. One submit button will return to the index page, and another submit button will re-direct me to some other action.
But how to know in controller that which submit button has been clicked?
here is my code
<?= $this->Form->create($User) ?>
<fieldset>
<legend><?= __('Add User') ?></legend>
<?php
echo $this->Form->control('first_name');
echo $this->Form->control('last_name');
echo $this->Form->control('status');
?>
</fieldset>
<?= $this->Form->submit(__('Save & Exit', array('name'=>'btn1'))) ?>
<?= $this->Form->submit(__('Save & Add Educational Details', array('name'=>'btn2'))) ?>
<?= $this->Form->end() ?>
in my controller i have written this
if(isset($this->request->data['btn1'])) {
return $this->redirect(['action' => 'index']);
} else if(isset($this->request->data['btn2'])) {
return $this->redirect(['controller' => 'educationQualifications', 'action' => 'add']);
}
but I am not able to get which button has been clicked..
Please tell how can I achieve this?
Thanks in advance
What ever you did is right but a small mistake, You have to use isset() in if condition as if implicitly not check for isset(). Check the correction below
if(isset($this->request->data['btn1'])) {
return $this->redirect(['action' => 'index']);
} else if(isset($this->request->data['btn2'])) {
return $this->redirect(['controller' => 'educationQualifications', 'action' => 'add']);
}
Or you can try this, you have to give the same name for the buttons.
In your view
<?= $this->Form->submit(('Save & Exit'), array('name'=>'btn')) ?>
<?= $this->Form->submit(('Save & Add Educational Details'), array('name'=>'btn')) ?>
In your controller
if($this->request->data['btn']=='Save & Exit') {
return $this->redirect(['action' => 'index']);
} else if($this->request->data['btn']=='Save & Add Educational Details')) {
return $this->redirect(['controller' => 'educationQualifications', 'action' => 'add']);
}

Yii2: getting error while page load '$model not defined'

I have developed form to allow owner to create team. code is:
<?php $form = ActiveForm::begin(['id' => 'team-create-form', 'action' => ['site/create-team-form'], 'options' => array('role' => 'form')]);
<div class="col-lg-10 form-group" id="createTeamForm" style="margin-top: 15px;">
<div class="col-lg-4">
<?= $form->field($model, 'team_name',['template' => "{label}\t{input}\n{error}"])->textInput(array('placeholder'=>'Enter team name....')); ?>
</div>
<div class="col-lg-4">
<?= $form->field($model, 'team_description',['template' => "{label}\t{input}\n{error}"])->textInput(array('placeholder'=>'Enter team Description....')); ?>
</div>
<div class="col-lg-2">
<?= Html::submitButton('Submit', ['class' => 'btn btn-danger', 'id' => 'tsubmit', 'style' => 'margin-top: 22.5px; margin-right: 15px;']) ?>
</div>
</div>
I have tried loading the page with the above code but it is showing me error "$model not defined". How to resolve that. Am i need to add something in the main-local.php???
public function actionLogin()
{
$model = new LoginForm();
$session = Yii::$app->session;
if ($model->load(Yii::$app->request->post()) && $model->login()) {
$collection1 = Yii::$app->mongodb->getCollection('users');
$teamid = $collection1->findOne(array('username' => $model->email_address));
$session->set('id', $teamid['_id']);
$session->set('name', $teamid['name']);
$session->set('username', $model->email_address);
$collection2 = Yii::$app->mongodb->getCollection('teamdashboard');
$teams = $collection2->find(array('admin' => $model->email_address));
$model1 = new TeamCreateForm();
return $this->render('dashboard', ['model'=>$model1, 'teams'=> $teams]);
} elseif($session->isActive){
$username = $session->get('username');
$collection = Yii::$app->mongodb->getCollection('users');
$teams = $collection->findOne(array('username' => $username));
return $this->render('dashboard', ['teams'=>$teams]);
}else{
$this->layout = 'index';
return $this->render('login', ['model' => $model]);
}
}
I have renamed the productpage as dashboard for better understanding.
Now when i run this & logs in, The address bar url shows url:..../web/index.php?r=site/login whereas it should show me url:..../web/index.php?r=site/dashboard & shows me the view of dashboard.
When i refresh the page, i brings me back to the login...
Did you use $model in dashboard view? If you do - you need to pass it (the same way as the login).
You have to send the $model to the view. The view only knows variables if you send it to it.
I have no idea what you mean with the address bar. The address bar has nothing to do with what you send to the view.
EDIT
Your entire way of thinking is strange. Why would u show different views depending if the person is registered or not?
return $this->render('dashboard', ['teams'=>$teams]);
return $this->render('login', ['model' => $model]);
User redirect with parameters to move the customer to another page. Having an URL like /login that actually shows a dashboard is not logical.

Zend subform view script render

I would rather not deal with decorators as my form design is not exactly straight forward, but i would like to keep the functionality of validating the forms.
So i have it set up where sub forms are working correctly, but when i try to style it manually in my viewscript i get the name without the parent. I've seen other posts that are similar, but i haven't found a solution.
Example:
This is in my view script
<?php echo $this->form->username->renderViewHelper();?>
I then get
<input type="text" value="" id="username" name="username">
When rendered. It should be
<input type="text" value="" id="form1-username" name="form1[username]">
How do i get that form1 portion?
Thanks!
Edit
Ok, so i found one way.
By using belongTo, it works:
$form1->addElements(array(
new Zend_Form_Element_Text('username', array(
'belongsTo' => 'form1',
'required' => true,
'label' => 'Username:',
'filters' => array('StringTrim', 'StringToLower'),
'validators' => array(
'Alnum',
array('Regex',
false,
array('/^[a-z][a-z0-9]{2,}$/'))
)
))
));
Is there a better way to do this or is this the only way?
Edit2
public function prepareSubForm($spec){
if (is_string($spec)) {
$subForm = $this->{$spec};
} elseif ($spec instanceof Zend_Form_SubForm) {
$subForm = $spec;
} else {
throw new Exception('Invalid argument passed to ' .
__FUNCTION__ . '()');
}
$this->setSubFormDecorators($subForm)
->addSubmitButton($subForm)
->addSubFormActions($subForm);
return $subForm;
}
public function setSubFormDecorators(Zend_Form_SubForm $subForm){
$subForm->setDecorators(array(
'FormElements', \\<--- I tried to change this to PrepareElements before.
array('HtmlTag', array('tag' => 'dl',
'class' => 'zend_form')),
'Form',
));
return $this;
}
I believe you can get your desired output just by using:
<?php echo $this->form->username; ?>
I get the expected output when calling this without renderViewHelper. This is also without any special code for decorators or preparing sub forms. All I had to do was add belongsTo to the form element.
UPDATED:
If you set this to be your default decorator, you can eliminate the dd/dt tags from rendering, instead it will use a div. Then you may be closer to getting the custom output you want. You can change the tag in HtmlTag from div to whatever tag you would like to wrap your elements in. This is what I use mostly:
array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('tag' => 'div', 'class' => 'form-div')),
array('Label', array('class' => 'form-label', 'requiredSuffix' => '*'))
);
This is the default for Zend Framework:
array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('tag' => 'dd', 'id' => array('callback' => $getId)))
array('Label', array('tag' => 'dt'))
);
Note that file, and submit/button elements use different decorators.
Also see this answer