I'm using Ajax validation in my widget. here is the code.
Widget function
public function run(){
if(!Yii::app()->user->isGuest){
$this->controller->redirect('/');
}
$model= new LoginForm;
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
// blah blah.......
Widget View:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'login-form',
'enableAjaxValidation'=> true,
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
)); ?>
<div class="row">
<?php echo $form->textField($model,'username',array('placeholder'=>'email','class'=>'form-control')); ?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->passwordField($model,'password',array('placeholder'=>'password','class'=>'form-control')); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Login', array('class'=>'btn btn-primary btn-block')); ?>
</div>
...
Right now the form is not submitting. After I click login nothing happens.
If I make enableAjaxValidation fale, form works but not AJAX.
If I make enableClientValidation false, form works but still no AJAX.
Any ideas? Thanks.
The thing is you are using a single submit button, instead of an ajax submit button.
For this, you may use, for example, an ajaxSubmitButton widget from Yii Bootstrap (or Yii booster).
So, in the SiteController :
...
$model= new LoginForm;
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
if(isset($_POST['LoginForm']))
{
$model->unsetAttributes();
$model->attributes=$_POST['LoginForm'];
if($model->validate() && $model->login())
{
$array = array('login' => 'success');
$json = json_encode($array);
echo $json;
Yii::app()->end();
}
else{ //This is the important point
if(Yii::app()->getRequest()->getIsAjaxRequest())
{
$array=$model->getErrors();
$json = json_encode($array);
echo $json; //JSON containing the errors set in /models/LoginForm.php
Yii::app()->end();
}
}
}
...
In your view:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'login-form',
'enableAjaxValidation'=> true,
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
));
?>
<div class="row">
<?php echo $form->textField($model,'username',array('placeholder'=>'email','class'=>'form-control')); ?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->passwordField($model,'password',array('placeholder'=>'password','class'=>'form-control')); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row" >
<?php
/** THIS IS THE AJAX SUBMIT BUTTON **/
$this->widget('bootstrap.widgets.TbButton', array(
'buttonType' => 'ajaxSubmit',
'label' => 'Login',
'ajaxOptions' => array(
'success' =>
'function(data){
var obj = $.parseJSON(data);
if(obj.login=="success"){
//...
// $(location).attr("href","BASEURL/someController/someAction")
}
else{
if("username" in obj){
$("#LoginForm_username_em_").text(obj.username[0]);
$("#LoginForm_username_em_").show();
$("#LoginForm_username").css({"background":"#FEE","border-color":"#C00"});
}
if("password" in obj){
$("#LoginForm_password_em_").text(obj.password[0]);
$("#LoginForm_password").css({"display":"block"});
$("#LoginForm_password").css({"background":"#FEE","border-color":"#C00"});
}
$("#LoginForm_password_em_").show();
}
}'),
));
?>
</div>
In order to use the ajaxSubmitButton widget of Yii Bootstrap (or Yii Booster), you have to download it from http://yiibooster.clevertech.biz/, extract it in your /protected/extensions folder and include it in /protected/config/main.php :
...
Yii::setPathOfAlias('bootstrap',dirname(__FILE__).'/../extensions/bootstrap'); //booster insead of bootstrap if you download the Yii Booster.
return array(
...
'components'=>array(
...
'bootstrap'=>array(
'class'=>'ext.bootstrap.components.Bootstrap', // assuming you extracted bootstrap under extensions
),
)
)
Yii Booster has many other widgets, for this reason I use it. If you don't want to use Yii booster for the ajax submit button, just use the CHtml::ajaxSubmitButton
Ajax validation needs a bit of care.
Please check response at console for ajax call. In ajax validation the output of ajax call should be pure json. In case of ajax validation from widget may include some html with response of ajax call.
have a look at http://www.yiiframework.com/forum/index.php/topic/12222-ajax-validation-in-widget-does-not-work/ hope it may help you.
Related
I'm very new to Yii, and trying to understand an existing web app, so please bear with me.
I've been having issues with a certain function, that seems to fail retaining data whenever actionView is calledhere, but I thought perhaps I was going about this problem all wrong.
Instead, I thought perhaps the button could directly run the function from the controller, instead of... whatever it was doing prior.
I looked at a sample here that had this:
<?php echo CHtml::submitButton('CSV Report', array('submit'=>'getReport')); ?>
Where getReport is the function in my controller (actionGetReport).
Unfortunately, it's not working. Here's the code of my _commentform.php:
<?php $post = $forum; ?>
<?php $comment = $model; ?>
<div id="comment_form<?=$post->id?>" class="other-member-comment-box">
<?php
$user=Persons::model()->findByAttributes(array('party_id'=>Yii::app()->user->id));
$country=Lookup_codes::model()->findByAttributes(array('id'=>$user->country));
$location = empty($country) ? '' : 'from '.$country->name;
?>
<div class="user-profilepic">
<a href="<?php echo Yii::app()->createUrl('persons/view/id/'.$user->showViewLinkId())?>"><img src="<?php
if(!empty($user->image) AND file_exists( Yii::getPathOfAlias('webroot').'/images/profile_picture/'.$user->party_id . $user->image)){
echo Yii::app()->request->baseUrl.'/images/profile_picture/'.$user->party_id . $user->image;
} else echo Yii::app()->request->baseUrl.'/images/profile_picture/NA.jpg';
?>"></a>
</div>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'comment-form',
'action'=>Yii::app()->createUrl('forum/view/id/'.$forum->id),
'enableAjaxValidation'=>false,
)); ?>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->hiddenField($model,'node_type_id',array('value'=>'7')); ?>
<?php echo $form->error($model,'node_type'); ?>
</div>
<div class="row">
<?php echo $form->hiddenField($model,'content_id',array('value'=>$forum->id)); ?>
<?php echo $form->error($model,'content_id'); ?>
</div>
<div class="row">
<?php echo $form->hiddenField($model,'category',array('value'=>$forum->category)); ?>
<?php echo $form->error($model,'category'); ?>
</div>
<div class="row">
<?php echo $form->textArea($model,'content',array('rows'=>6, 'cols'=>90),array('id'=>'sample')); ?>
<?php echo $form->error($model,'content'); ?>
</div>
<input type="hidden" value="<?php echo $view; ?>" id="view" name="view"/>
<div class="row buttons">
<?php
if ($view == 'view'){
if ($model->isNewRecord) {
echo CHtml::submitButton('Reply', array('id'=>'comment'.$comment->id));
} else {
echo CHtml::button('Save', array('submit'=>'updatecomment'));
}
}?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
</div>
And here's the UpdateComment function from my controller:
public function actionUpdateComment()
{
Yii::log(CVarDumper::dumpAsString("ForumController: Update COMMENT!"));
Yii::log(CVarDumper::dumpAsString($_POST['Comment']));
exit();
}
I'm not exactly sure what I'll get by the $_POST['Comment'], but if the code worked, I'd very least expect it to log out the "ForumController: Update COMMENT!". It doesn't.
I tried changing the submitButton to button, but that just kills the button function entirely.
Next, I tried this answer here.
So I changed the submitButton code to this:
echo CHtml::submitButton($model->isNewRecord ? 'Reply' : 'Save',array('id'=>'comment'.$comment->id));
And added this to the end:
<script>
$(document).ready(function() {
$('#text_form_submit').click(function(ev) {
ev.preventDefault();
$.ajax({ type: 'POST', dataType: 'JSON',
url: '<?php echo Yii::app()->createUrl("forum/UpdateComment"); ?>',
success:function(data){
if(data !== null) {
$('#Text_group').val(data);
$('#text-form').submit();
}
},
error: function() {
alert("Error occured!!!.");
},
});
return false;
});
});
</script>
Not exactly sure what the code does, other than call a function as well, but as well, it doesn't work (I also changed POST from GET and back).
Any suggestions? I feel like CActiveForm is to blame here, but even modifying that causes the site to fail in loading pages.
You have a long question and could be you should split your question in more question with simple question each ..
A firts answer the submit button don't contain the target function see this doc
http://www.yiiframework.com/doc/api/1.1/CHtml#submitButton-detail
the target function (php controller/action) is defined in form .. this is from html .. is the form definition that define the target for the submitted data ..
if you want execute the actionGetReport you should define the target in form action
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'comment-form',
'action'=>Yii::app()->createUrl('yourController/actionGetReport'),
'enableAjaxValidation'=>false,
)); ?>
I'm unable to get the selected value after the page refreshes due to validation failure at server-side for only dropdownlist.
Here is my code.
$model=new Employee;
if(isset($_POST['Employee']))
{
$_POST['Employee']['acc_id'] = Yii::app()->session['acc_id'];
$model->attributes=$_POST['Employee'];
if($model->save())
$this->redirect(array('view','id'=>$model->emp_id));
}
$this->render('create',array(
'model'=>$model,
));
and my dropdown list in _form.php in views
<div class="row">
<?php echo $form->labelEx($model,'emp_type'); ?>
<?php echo CHtml::dropDownList('Employee[emp_type]', $model,Type::model()->jobTypesList,
array('empty' => 'Select a job type'))?>
<?php echo $form->error($model,'emp_type'); ?>
</div>
change this line
<?php echo CHtml::dropDownList('Employee[emp_type]', $model,Type::model()->jobTypesList,array('empty' => 'Select a job type'))?>
to
<?php echo $form->dropDownList($model,'emp_type', Type::model()->jobTypesList,array('empty' => 'Select a job type'))?>
When we create a yii webapp using yiic, a login function is already made.
However, I want to use the navbar as a login widget (and bootstrap for design) as shown in here. That's when I encountered my problem. When I try to login using the toolbar/widget, the details I have input are displayed in the browser's bar and then nothing. See here.
This my LoginWidget.php
<?php class LoginWidget extends CWidget {
public function run() {
$model=new LoginForm;
$form= $this->beginWidget('CActiveForm', array(
'id'=>'login-form',
// 'action'=>
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
)
));
echo $form->errorSummary($model);
?>
<div class="form-group">
<?php echo $form->textField($model,'username',array('placeholder'=>'Employee Code','class'=>'form-control')); ?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="form-group">
<?php echo $form->passwordField($model,'password',array('placeholder'=>'Password','class'=>'form-control')); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<?php
echo CHtml::submitButton('Sign in', array('class'=>'btn btn-success'));
$this->endWidget();
}
} ?>
This is my Controller (just the necessary part).
public function actionIndex()
{
$model=new LoginForm;
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if($model->validate() && $model->login())
$this->redirect('myprofile/index');
}
// display the login form
$this->render('index',array('model'=>$model));
// renders the view file 'protected/views/site/index.php'
// using the default layout 'protected/views/layouts/main.php'
// $this->render('index');
}
When I try to login using localhost/project/index.php/site/login, it works.
Make sure the form sends data with POST
$form= $this->beginWidget('CActiveForm', array(
'id'=>'login-form',
'method' => 'POST',
'enableClientValidation'=>true,
'clientOptions'=>
array(
'validateOnSubmit'=>true,
)
));
I am trying to do simple contact us page with flashmessenger helper plugin.
I have implemented it as below, but my problem is i have to submit the form twice to get the flashmessagers showing in the page.
What i am i doing wrong here ..
show the messages on the first submit ?
how do i hide the form the after submit ?
in my controller
// Add content to this method:
public function contactAction()
{
$form = new ContactForm();
$form->get('submit')->setValue('Submit');
$request = $this->getRequest();
if ($request->isPost()) {
$contact = new Contact();
$form->setInputFilter($contact->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$data=$form->getData();
//var_dump($data);
$mail = new Mail\Message();
$mail->setBody($data['comment'])
->setFrom($data['email'], $data['name'])
->addTo(IEMAIL, COMPANY )
->addReplyTo($data['email'], $data['name'])
->setSubject($data['subject']);
$transport = new Mail\Transport\Sendmail();
$transport->send($mail);
$this->flashMessenger()->addMessage('Thanks you for the submission ');
}
else{
$this->flashMessenger()->addMessage('Opps somethinge went wrong ..!');
}
}
/**/
return new ViewModel(array(
'customMessage' => 'Welcome to the sales',
'form' => $form
));
}
IN my view i have the coding as
<?php
$title = 'Contact Us';
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<?php echo $this->customMessage ?>
<?php
if ($this->flashMessenger()->hasMessages()):
echo $this->flashMessenger()->render('success', array('alert', 'alert-danger'));
// In any of your .phtml files:
$flash = $this->flashMessenger();
$flash->setMessageOpenFormat('<div%s>
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">
×
</button>
<ul><li>')
->setMessageSeparatorString('</li><li>')
->setMessageCloseString('</li></ul></div>');
echo $flash->render('error', array('alert', 'alert-dismissable', 'alert-danger'));
echo $flash->render('info', array('alert', 'alert-dismissable', 'alert-info'));
echo $flash->render('default', array('alert', 'alert-dismissable', 'alert-warning'));
echo $flash->render('success', array('alert', 'alert-dismissable', 'alert-success'));
?>
<? endif ?>
<?php
$form->setAttribute('action', $this->url('contact', array('action' => 'submit')));
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formRow($form->get('name'));
echo $this->formRow($form->get('email'));
echo $this->formRow($form->get('subject'));
echo $this->formRow($form->get('comment'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag();
The flash messenger does not work in the way you are expecting. It is designed for showing messages to the user after a redirect. To do this it adds any messages you pass to it to a session container so they can be retrieved on the next request. This behaviour (Post/Redirect/Get) is a common pattern in web applications as it reduces of the chance of a user accidentally re-submitting form submissions by refreshing the page.
If you add a redirect after your $transport->send($mail);, then the successful submissions should work how you expect. For the failed ones to work you'll need to write your own helper that does same-request messaging as well (which is what I normally do). Instead you might want to get rid of the fail message and just let the form's inbuilt error messaging do its thing.
Change this code in controller...
$message = '';
$flashMessenger = $this->flashMessenger();
if ($flashMessenger->hasMessages()) {
$message = $flashMessenger->getMessages();
}
And in View
<?php if(is_array($message) && count($message) > 0){
foreach($message as $messageKey => $messageValue){?>
<div style= "color:red"> <?php echo $messageValue; ?> </div>
<?php } } ?>
Whenever the page is loaded or reloaded through a redirect/render/refresh, it seems to auto submit the last information that was submited to the database constantly. I tried adding restrictions to the add method but it seems to hold information from the previous submit, which allows it to by pass the isset $_POST.
view which contains the actionform.
<div class="form offset2">
<?php $form = $this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'userTeam-form',
'enableAjaxValidation'=>false,
// Check thta the action method below is correct
'action'=> array('/User/AddTeamMessage', 'id' => $model->id),
)); ?>
<!--
Would allow user to access specific team messages and control how much gets display.
still under construction.
-->
<div class="row">
<?php
echo CHtml::dropDownList("teamId", 'id', Chtml::listData($model->memberOfTeams, 'id', 'teamName'),array(
'empty'=>'Select Team',
'ajax'=>array(
'type'=>'POST', // request type
'url'=>CController::createUrl('DisplayMessage'),
'update'=>'#teamMessages', // selector to update
'data'=>array('teamId'=>'js:this.value'),
)
)
);
echo CHtml::dropDownList("teamMessages", '', array(), array('prompt'=>'Select Messages'));
?>
</div>
<!--
Only works for coaches
Allows coaches to submit team messages.
-->
<?php if ($model->isCoach()) { ?>
<!-- Text area for the coach to enter messages in -->
<textarea name="addTeamMessage" class="span5" rows="5" style="resize: none;"></textarea>
<!-- submit button -->
<?php echo CHtml::submitButton('Submit Message', array(
'class' => 'btn btn-primary',
'name' => 'submitTeamMessage'
)); ?>
<?php } ?>
<!-- end the widget. everything will be send to UserController/AddTeamMessages -->
<?php $this->endWidget(); ?>
controller when the activeform is surppose to be trigger.
/* add a team message submitted by the coach of the team */
public function actionAddTeamMessage($id)
{
/* check if team and message aren't null */
if(isset($_POST['submitTeamMessage']))
{
if(isset($_POST['teamId']['addTeamMessage']))
{
try
{
/* creates a new message */
$teamModel = new TeamMessage;
$teamModel->teamId = $_POST['teamId'];
$teamModel->content = $_POST['addTeamMessage'];
$teamModel->sendTime = new CDbExpression('NOW()');
$teamModel->save();
}
catch(Exception $e)
{
echo "Unable to save.";
}
}
}
/* render the profile page for the current user */
$user=User::model()->findByPk($id);
$this->render('profile', array(
'model' => $user));
}
Is it also sending the data when you go to the page when logged in as a Coach?
if not:
the problem is likely to be the submit button, since the active form can't be submitted.
place it outside of the isCoach if statement.
<?php if ($model->isCoach()) { ?>
<!-- Text area for the coach to enter messages in -->
<textarea name="addTeamMessage" class="span5" rows="5" style="resize: none;"></textarea>
<?php } ?>
<!-- submit button -->
<?php echo CHtml::submitButton('Submit Message', array(
'class' => 'btn btn-primary',
'name' => 'submitTeamMessage'
)); ?>