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'))?>
Related
Hope you all doing fine.
Scenario
I have a junction model resumeSkills that takes the id of resume and the id of skill from different tables and another field "proficiency level" to determine the expertise in that particular skill.
I have multiple instances of this model loaded in my page based on "Add New" button click (which triggers a Jquery AJAX callback which interns, creates a model against given index counter).
Every model instance is validated based on model rules defined so it works fine if I have different values selected for every instance created.
Target
Now, I want to add skills in a way that If I select "php" in any model-instance in my view either I am not able to select "php" in any of newly generated model-instances or I don't see in there respective drop-down/tags.
Problem
Now if I select the same value for multiple instances (above figure), Validation fails against second or later record as I have rule that skills can not be duplicated against a resume.
This is where I need Help from the community.
Here is my controller action method to add new model instance (record) in the view (append the content container)
public function actionAddNewRecord($idresume, $index)
{
$model = new OresumeResumeSkill();
$model->idresume = $idresume;
$model->isDeleted = 0;
$model->isFromDb = 0;
$response = [];
$response['content'] = $this->renderPartial('_partials/_add_new_form', [
'model' => $model, 'i'=>$index
]);
return Json::encode($response);
}
Here is the code to my main partial file:
_edit_file.php
<div class="row">
<!-- container that has form and its operations in it -->
<div class="col-xs-12">
<?php
$form = ActiveForm::begin([
'id' => 'form_edit_resume_skill_multiple',
'options' => [
'enctype' => 'multipart/form-data',
'class' => 'section_form',
],
]);
?>
<div id="add_new_record_container">
<!--
Add new Item related item_container will be placed in here dynamically in parallel
This loaded content is based on _add_new_form partial view
Content is added via AJAX request caused by btn_add_new_record
-->
</div>
<div class="row form_controls">
<div class="col-xs-12 text-right">
<input type="hidden" name="hdnCounter" id="hdnCounter" value="<?php echo count($skills); ?>" />
<?php echo Html::a(T::t('main', 'Add New'), ['/oresume/resume-skill/add-new-record', 'idresume'=>$model_resume->idresume], ['id'=>'btn_add_new_record', 'class'=>'btn btn-primary' ]); ?>
</div>
<div class="col-xs-12 text-right">
<?php echo Html::a(T::t('main', 'Cancel'), ['/oresume/attachment/discard-all-drafts'], ['class'=>'btn btn-default', 'id'=>'btnDiscardChanges', 'data'=>['confirm_message'=>T::t('main', 'Discard Changes?'), ] ]);?>
<?php echo Html::submitButton(T::t('main', 'Save Changes'), ['class' => 'btn btn-success']); ?>
</div>
</div>
<?php $attributes = Json::htmlEncode($form->attributes);?>
<script type="text/javascript">
jQuery(document).ready(function($){
<?php
$options = Json::htmlEncode($form->options);
$attributes = Json::htmlEncode($form->attributes);
?>
$("#<?php echo $form->options['id'];?>").yiiActiveForm(<?php echo $attributes;?>, <?php echo $options;?>);
$(".resume_skills").select2({
tags: true,
multiple: true,
maximumSelectionLength: 1,
language: "<?php echo \Yii::$app->language; ?>",
allowClear: true,
placeholder: {
idskill: "",
placeholder: "<?php echo T::t('main', 'Please select'); ?>"
},
});
var attributes = <?php echo $attributes;?>;
for(var i = 0; i < attributes.length; i++) {
$("#form_edit_resume_skill_multiple").yiiActiveForm('add', attributes[i]);
}
});
</script>
<?php ActiveForm::end(); ?>
</div>
<!-- //container that has form and its operations in it -->
</div>
Here is the code for my sub_partial file (to add a new model instance):
_add_new_form.php
$title = T::t('main', 'Add New Record');
$skills = OresumeSkill::listSkills();
$proficiencyLevels = OresumeResumeSkill::listProficiencyLevels();
$form = ActiveForm::begin();
?>
<div class="col-xs-12 item_container">
<div class="row single_value_row">
<div class="col-xs-6">
<?php echo $form->field($model, "[$i]idskill")->dropDownList($skills, ['style'=>['width'=>'100%'], 'class'=>'resume_skills', 'placeholder'=>T::t('main', 'Please select')]); ?>
</div>
<div class="col-xs-5">
<?php echo $form->field($model, "[$i]level")->dropDownList($proficiencyLevels, ['prompt' => T::t('main', 'Please Select')]); ?>
</div>
<div class="col-xs-1 text-left">
<button class="btn btn-danger pull-right btn_remove_record" id="btnRemoveResumeSkill-<?php echo $i;?>"><?php echo T::t('main', '<i class="fa fa-times"></i>'); ?></button>
<?php echo $form->field($model, "[$i]isDeleted")->hiddenInput(['class'=>'isDeleted_input'])->label(false); ?>
<?php echo $form->field($model, "[$i]isFromDb")->hiddenInput(['class'=>'isFromDb_input'])->label(false); ?>
</div>
</div>
<script type="text/javascript">
jQuery(document).ready(function($){
$("#form_edit_resume_skill_multiple").yiiActiveForm('add', 'OresumeResumeSkill[<?php echo $i; ?>]');
$(".resume_skills").select2({
tags: true,
multiple: true,
maximumSelectionLength: 1,
language: "<?php echo \Yii::$app->language; ?>",
allowClear: true,
placeholder: {
idskill: "",
placeholder: "<?php echo T::t('main', 'Please select'); ?>"
},
});
<?php $attributes = Json::htmlEncode($form->attributes);?>
var attributes = <?php echo $attributes; ?>;
for(var i = 0; i < attributes.length; i++) {
$("#form_edit_resume_skill_multiple").yiiActiveForm('add', attributes[i]);
}
});
</script>
</div>
<?php ActiveForm::end(); ?>
And here is the code for my action that handles the dynamically generated models and save them in db.
Public function actionGetResumeSkills($idresume)
{
$model_resume = OresumeResume::findOne($idresume);
$models = OresumeResumeSkill::getResumeSkills($model_resume->idresume);
$response = [];
$postedArray = \Yii::$app->request->post('OresumeResumeSkill');
// print_r($postedArray);
if( count($postedArray) ) //case: Its a postback and we have some models in it
{
if(count($models) < count($postedArray) )//case: postback has more number of models as compared to in db
{
// Generate empty models array to be filled by loadMultiple() method of model class
// create emoty models and add in models array counter so that
// we've equal number of sent / recieved models for processing
for ($i=count($models); $i< count($postedArray); $i++ )
{
$model = new OresumeResumeSkill();
$model->idresume = $idresume;
$models[] = $model;
}
}
}
if( count($models) == 0) // we need to check if this array has something to process
{
$response['status'] = false;
$response['message'] = T::t('main', 'No records found to process');
}
if(OresumeResumeSkill::loadMultiple($models, \Yii::$app->request->post())) // load multiple models of models array
{
$status = true;
foreach ($models as $model)
{
// Delete models that are flaged to do so
// execute continue statement on deletion
// Validate and save models that are to be saved/updated
$model->idskill = OresumeResumeSkill::getSkill($model->idskill);
$model->level = ($model->level != null)? $model->level : OresumeResumeSkill::LEVEL_BEGINNER;
if( $model->validate() ) // Case: Model data is valid
{
// Save Model in database
$status &= $model->save();
}
else
{
$status = false;
// print_r($model->errors['idskill'][0]);
$response['message'] = T::t("main", "Storing of record \"{$model->idskill0->name}\" got some validation issues\n");
}
}
if($status)
{
$model_resume = OresumeResume::findOne($model->idresume);
$models = OresumeResumeSkill::getResumeSkills($model->idresume);
$response['status'] = true;
$response['content'] = $this->renderPartial('_partials/_edit_form', ['model_resume' => $model_resume, 'skills' => $models]);
$response['counter'] = count($models);
$response['message'] = T::t('main', 'Record(s) updated Successfully');
}
else
{
$response['status'] = false;
// $response['message'] = T::t('main', 'Records could not be updated.\n Something went wrong');
}
}
else // case: page loads for the first time
{
$response['content'] = $this->renderPartial('_partials/_edit_form', ['model_resume'=>$model_resume, 'skills' => $models]);
}
return Json::encode($response);
}
Any Help is Appreciated.
thankx in advance.
I'm reading this on a phone so there are a few parts of your code I'm not sure I totally get and I won't be able to type much. However, from my understanding, you don't want already selected skills to show up in next drop down.
You can have a hidden field to keep the IDs of selected skills (comma separated) and pass that as an argument to the listSkills method. Means your listSkills method will change a bit to accept a parameter.
In your listSkills method you have to use a where clause that says where skill ID NOT IN the list of IDs coming from the hidden field. Means you will be selecting back only the skills that have not been selected before into your array for the drop down.
Sorry I'm on a phone, I can't add code samples.
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.
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 get a value from a drop-down list in order to insert in a table in my dataBase. I am using ajax in order to capture this value and draw a button that will insert the value in my database when the user clicks on it.
This is my code :
Yii::app()->clientScript->registerScript('register_script_name', "
$('#editButton').click(function(){
alert('edit');
return false;
});
", CClientScript::POS_READY);
<div class="row">
<?php echo $form->labelEx($model,'Escolha a opção correta <span class="required">*</span>')?>
<?php echo $form->dropDownList($model, 'Opcoes_idOpcoes',$this->getOpcoesResposta(),
array(
'ajax' => array(
'type' => 'POST',
'url'=>$this->createUrl('perguntaOpcoes/State'),
'data'=>array('Opcoes_idOpcoes'=>'js: $(this).val()'),
'update' => '#data',
)
));
?>
</div>
<div id="data">
</div>
And this is my code in controller:
public function actionState()
{
$data= $_POST['Opcoes_idOpcoes'];
echo CHtml::button("Edit",array('title'=>"Edit",'id'=>"editButton",'onclick'=>'edit()'));
}
Can anyone help me ?
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'
)); ?>