i have a create form, Which posts value to actionCreate() like
Form - dropdown
Dynamic form depending on the dropdown above
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']);?>
<?=
$form->field($model, 'techpark_id')->dropDownList($techparks, ['prompt' => '- Choose a Techpark -',
'onchange' => '
$.get( "' . Yii::$app->urlManager->createUrl('campaign-request/techpark-details?id=') . '"+$(this).val(), function( data ) {
$( "#details" ).html( data );
});
']);
?>
<div id="details">
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Now the onchange event in the dropdown -> techpark_id will post id to campaign-request/teckpark-details
Yii::$app->urlManager->createUrl('campaign-request/techpark-details?id=7)
This actionTechparkDetails will renderPartial like this with values to dropdown list depending upon the value $id
public function actionTechparkDetails($id) {
$details = [new \app\models\CampaignRequestAdDetails];
$connection = Yii::$app->getDb();
$command = $connection->createCommand('
SELECT adspace_type_id,type,number_of_adspace,number_of_filled,adspace_value FROM `Techpark`
JOIN techpark_adspace ON techpark.id = techpark_id
JOIN adspace_type ON adspace_type_id = adspace_type.id
WHERE techpark.id=:id', [':id' => $id]);
$result = $command->queryAll();
$adspace_type_id = ArrayHelper::map($result, 'adspace_type_id', 'type');
return $this->renderAjax('_campaignDetails', [
'details' => (empty($details)) ? [new \app\models\CampaignRequestAdDetails] : $details,
'adspace_type_id' => $adspace_type_id
]);
}
campaignDetails has a dynamic form which populates the value depending on the selected dropdown() value ($id)
My _campaignDetails.php
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']);?>
<div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Campaign details</h4></div>
<div class="panel-body">
<?php
DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
'widgetBody' => '.container-items', // required: css class selector
'widgetItem' => '.item', // required: css class
'limit' => 20, // the maximum times, an element can be cloned (default 999)
'min' => 4, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $details[0],
'formId' => 'dynamic-form',
'formFields' => [
'adspace_type_id',
'number_of_adspace',
],
]);
?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($details as $i => $detail): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<?php
// necessary for update action.
if (!$detail->isNewRecord) {
echo Html::activeHiddenInput($detail, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-4">
<?= $form->field($detail, "[{$i}]adspace_type_id")->dropDownList($adspace_type_id) ?>
</div>
<div class="col-sm-4">
<?= $form->field($detail, "[{$i}]number_of_adspace")->textInput() ?>
</div>
</div><!-- .row -->
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
Now when i fill up the form and submit, i am unable to get the values of form (_campaignDetails.php which was rendered partially), inside actionCreate().
And also the remove item is not working in the dynamic form. Which would perfectly working if rendered inside the same form(i have another form which works fine with add/remove item of dynamic form).
I am using widget to dynamic form github.com/wbraganca/yii2-dynamicform
OR tell me how can i achieve the above scenario in any other format/manner using differnt approach. If you donot get what i want to achieve is
Depending on a dropdown value, i want a dynamic form which collects input with respect to value selected.
Thanks
Related
I am working on an application that requires authentication, in Codeigniter 3. Rather then making my own authentication, I decided to use the Ion-Auth library.
Because I also use Bootstrap 4, I tried to add form-related classes to the form controls. I tried to replace:
<p>
<label for="new_password"><?php echo sprintf(lang('change_password_new_password_label'), $min_password_length);?></label> <br />
<?php echo form_input($new_password);?>
</p>
with:
<div class="form-group">
<?php $attributes = array(
'class' => 'form-control',
'placeholder' => 'New password',
'value' => $new_password
); ?>
<label for="new_password"><?php echo sprintf(lang('change_password_new_password_label'), $min_password_length);?></label> <br />
<?php echo form_input($attributes);?>
</div>
The code above throws the error message Array to string conversion.
What am I doing wrong?
You haven't specified what function you're calling but after looking Ion-Auth library, I'm guessing it's reset_password(). Regardless,
In your controller, the data is passed as -
$this->data['new_password'] = [
'name' => 'new',
'id' => 'new',
'type' => 'password',
'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
];
Now $new_password is an array in view. So, in order to give it value and pass extra attributes, you'll have to write -
<?php
$new_password['class'] = 'form-control';
$new_password['placeholder'] = 'New password';
$new_password['value'] = $_POST['new'] ?? ''; // if post request then submitted value else empty
echo form_input($new_password);
?>
This will produce -
<input type="password" name="new" value="123456" id="new" pattern="^.{4}.*$" class="form-control" placeholder="New password">
Edit
For form_submit, you can write -
echo form_submit('submit', 'submit', 'class="btn btn-block btn-md btn-success"');
or as an array -
echo form_submit(array(
'name'=>'submit',
'value' => 'submit',
'class' => 'btn btn-block btn-md btn-success'
)
);
This will produce -
<input type="submit" name="submit" value="submit" class="btn btn-block btn-md btn-success">
See if this helps you.
<div class="form-group">
<?php $attributes = [
'class' => 'form-control',
'placeholder' => 'New password',
'value' => $new_password
]; ?>
<label for="new_password"><?php echo sprintf(lang('change_password_new_password_label'), $min_password_length);?></label> <br />
<?php echo form_input($attributes);?>
</div>
try this
Here is the working login form, for whoever needs an example:
<?php echo form_open("auth/login");?>
<div class="form-group">
<?php $identity['class'] = 'form-control';
echo lang('login_identity_label', 'identity');
echo form_input($identity);?>
</div>
<div class="form-group">
<?php $password['class'] = 'form-control';
echo lang('login_password_label', 'password');
echo form_input($password);?>
</div>
<div class="form-group">
<?php $remember['class'] = 'form-control';
echo lang('login_remember_label', 'remember');
echo form_checkbox('remember', '1', FALSE, 'id="remember" class="ml-2"');?>
</div>
<div class="form-group">
<?php echo form_submit('submit', lang('login_submit_btn'), 'class="btn btn-block btn-md btn-primary"');?>
</div>
<?php echo form_close();?>
I'm using ActiveForm and I would need to display the validation errors not close to the input fields but rather at the top of the form.
As shown in the sample code below, setting errorOptions I avoid to display the error message in the default position.
Ajax validation is working but the $form->errorSummary($model) doesn't show any message, even if here it seems like it should and in the documentation I could not find a clear answer.
Also, adding Html::error($model, 'username') does not help with Ajax validation.
<?php
$form = ActiveForm::begin([
'id' => 'test-form',
'options' => ['class' => 'form-horizontal'],
'enableAjaxValidation' => true,
'enableClientValidation' => true,
])
?>
<?= $form->errorSummary($model) ?>
<?= Html::error($model, 'username') ?>
<div class="form-row">
<div class="form-group col-md-3">
<?= $form->field($model, 'username', ['errorOptions' => ['tag' => false]])->textInput()->label("Username") ?>
</div>
</div>
<?php ActiveForm::end() ?>
In Yii1.1 the validation errors can be displayed in a more flexible way, since you could define label, input and error individually. Something like this:
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username'); ?>
<?php echo $form->error($model,'username'); ?>
In that case you can simply move $form->error($model,'username'); anywhere within the form.
How is it possible to obtain the same results with Yii2 without using the Javascript API?
Display the Ajax validation errors for individual input at the top of the form.
Display the Ajax validation errors with errorSummary()
Edit
I forgot to mention that I'm using Bootstrap4 through the extension yii2-bootstrap4. Part of the problems I'm having with the error display may be related to this bug.
Considering the answer from #serghei-leonenco I add here some complete minimal code to replicate the problem.
Model
namespace frontend\models;
use Yii;
use yii\base\Model;
class AjaxForm extends \yii\base\Model
{
public $demo;
public function rules()
{
return [
// define validation rules here
[['demo'], 'required'],
[['demo'], 'string', 'length' => [2, 4]],
];
}
}
View
<div class="row">
<div class="col-lg-6">
<?php $form = ActiveForm::begin(['id' => 'test-form',
'options' => [
'class' => 'form-horizontal'],
'enableAjaxValidation' => true,
'enableClientValidation' => false,]) ?>
<div class="form-row">
<div class="form-group col-md-3">
<?php echo $form->field($model, 'demo', ['template' => '{error}']); ?>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">
<?= $form->field($model, 'demo')->textInput()->label("Demo") ?>
<?php echo $form->field($model, 'demo', ['template' => '{error}']); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-1 col-lg-11">
<?= Html::submitButton('Submit 1', ['class' => 'btn btn-primary','name' => 'submit1']) ?>
</div>
</div>
<?php ActiveForm::end() ?>
</div>
</div>
Controller
public function actionTestajax()
{
$model = new AjaxForm();
// Ajax validation
if (Yii::$app->request->isAjax){
$model->load(Yii::$app->request->post());
Yii::$app->response->format = Response::FORMAT_JSON;
$ret = ActiveForm::validate($model);
Yii::info("Ajax validation: " . json_encode($ret));
return $ret;
}
// form submit
if ($model->load(Yii::$app->request->post())) {
if($model->validate()){
// valid data received in $model
//var_dump($model);
return $this->render('testajax_submit', ['model' => $model]);
} else {
return $this->render('testajax', ['model' => $model]);
}
}
return $this->render('testajax', ['model' => $model]);
}
Out of the three <div class="invalid-feedback">Demo cannot be blank.</div>, only one is shown, the other two maintain the style .invalid-feedback {display: none;}.
The $form->errorSummary($model):
after the validation is performed, returns this:
<div style="display:none">
<p>Please fix the following errors:</p>
<ul></ul>
</div>
after the form is submitted, returns this:
<div class="alert alert-danger" style="">
<p>Please fix the following errors:</p>
<ul>
<li>Demo cannot be blank.</li>
<li>Demo cannot be blank.</li>
<li>Demo cannot be blank.</li>
</ul>
</div>
I did tested out $form->errorSummary(); and it does shows the desired output, but in the form of:
Please fix the following errors:
Please enter Username.
Like an option, you can do it this way:
<?php $form = ActiveForm::begin([
'id' => 'test-form',
'options' => ['class' => 'form-horizontal'],
'enableAjaxValidation' => true,
'enableClientValidation' => true,
]); ?>
<div class="form-group col-md-3">
<div class="error-block text-center">
<?php
$error = $form->field($model, 'username');
$error->template = '{error}';
echo $error;
?>
</div>
<?php
$username = $form->field($model, 'username');
$username->template = "{input}";
echo $username->textInput(['autofocus' => true]);
?>
</div>
<?php ActiveForm::end() ?>
The output will be right above the form field will be the response with:
Please enter Username
In view I have a form:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true, 'placeholder' => 'Name'])->label(false) ?>
<?= $form->field($model, 'phone')->textInput(['maxlength' => true, 'placeholder' => 'Phone'])->label(false) ?>
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
Controller is:
if ($model->load(Yii::$app->request->post()) && $model->save()) {
\Yii::$app->session->setFlash('success', 'Created');
}
return $this->redirect(Yii::$app->request->referrer);
Then in view I put a modal:
<?php if (Yii::$app->session->hasFlash('success')) :?>
<!-- <div class="container">
<?= Yii::$app->session->getFlash('success', null, true) ?>
</div> -->
<div class="modal hide fade" id="myModal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Modal header</h3>
</div>
<div class="modal-body">
<p><?= Yii::$app->session->getFlash('success', null, true) ?></p>
</div>
<div class="modal-footer">
Close
Save changes
</div>
</div>
<?php endif ;?>
And JS code is:
$(window).load(function(){
$('#myModal').modal('show');
});
I want to open success modal window after clicking submit button. But now nothing happens. Just reloads the page. How to do that I want? And please explain how to do that without reloading the page.
This might be no the best decidion, but i use class myAjaxModalClass and a simple js code, that submit all form with that class via ajax and parse json result:
{result:0, data:'new modal content'}
That allows me to load form with validation erros without page reloading. Also you may add your result status to submit redirect. Expample:
{result: 2, url:'http://yoursite.net'}
I have an application where user has to fill a lengthy form, so I split the form into three and created steps - Step 1, Step 2 etc. So it has to be convenient for users. Now I face a problem, after filling out the details, a text field shows an error. When using model->get Errors() the error is 'address cannot be blank'. When I use $_POST the arrays displays value for the field address. I started yii framework last week and I do not know where I have gone wrong. Any help appreciated.
The view code i use forloop to reduce my code -
<fieldset>
<?php if(!Yii::app()->user->hasFlash('success')):
Yii::app()->user->setFlash('warning','All Fields are mandatory!');
endif; ?>
<?php echo CHtml::errorSummary($model, null, null, array(
'class' => 'alert alert-danger col-lg-offset-2',
)); ?>
<?php $rrr = -1;
foreach($model->attributeLabels() as $a){ $rrr++;
if($rrr<27 && $rrr>=12){
?>
<div class="form-group">
<?php echo CHtml::activeLabel($model, $a, array('class' => 'col-lg-3 control-label')); ?>
<div class="col-lg-7">
<?php echo CHtml::activeTextField($model,array_keys($model->attributeLabels())[$rrr],array('value'=>'a','size'=>255,'maxlength'=>255,'class'=>'form-control formtype1')); ?>
</div>
</div>
<?php
}}
?>
<?php $rrr = -1;
foreach($model2->attributeLabels() as $a){ $rrr++;
if($rrr>1 && $rrr<6){
?>
<div class="form-group">
<?php echo CHtml::activeLabel($model2, $a, array('class' => 'col-lg-3 control-label')); ?>
<div class="col-lg-7">
<?php echo CHtml::activeTextField($model2,array_keys($model2->attributeLabels())[$rrr],array('value'=>'a','size'=>255,'maxlength'=>255,'class'=>'form-control formtype1')); ?>
</div>
</div>
<?php
}}
?>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-sm btn-primary" type="submit"><?php echo Yii::t("user", "Submit") ?></button>
</div>
</div>
</fieldset>
</form>
My model is not inserting my modify and access data that I select on my view.If my select option on my view is select option 1 it inserts value 0 even though 1 selected. Not sure why on model or view its not inserting the correct one?
Each controller has its own modify and access select option i would like to be able to insert if select 1 for enable or 0 disbale?
How can I make the both select options work with my model so inserts correct what have chosen.
Model Function
<?php
class Model_user_group extends CI_Model {
public function addUserGroup() {
$name = $this->input->post('name');
$controllers = $this->input->post('controller');
$access = $this->input->post('access');
$modify = $this->input->post('modify');
for($i=0;$i<count($controllers);$i++) {
$data = array(
'name' => strtolower($name),
'controller' => $controllers[$i],
'access' => $access,
'modify' => $modify
);
$this->db->insert($this->db->dbprefix . 'user_group', $data);
}
}
View
<?php echo Modules::run('admin/common/header/index');?>
<div id="wrapper">
<?php echo Modules::run('admin/common/menu/index');?>
<div id="page-wrapper" >
<div id="page-inner">
<div class="panel panel-default">
<div class="panel-heading clearfix">
<div class="pull-left" style="padding-top: 7.5px"><h1 class="panel-title"><?php echo $title;?></h1></div>
<div class="pull-right">
Cancel
<button type="submit" onclick="submit()" class="btn btn-primary">Save</button>
</div>
</div>
<div class="panel-body">
<?php echo validation_errors('<div class="alert alert-warning text-center">', '</div>'); ?>
<?php $data = array('class' => 'form-horizontal', 'id' => 'form-users-group');?>
<?php echo form_open_multipart('admin/users_group_add', $data);?>
<div class="form-group">
<?php $data = array('class' => 'col-sm-2');?>
<?php echo form_label('User Group Name', 'name', $data);?>
<div class="col-sm-10">
<?php $data1 = array('id' => 'name', 'name' => 'name', 'class' => 'form-control', 'value' => set_value('name'));?>
<?php echo form_input($data1);?>
</div>
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>Controller Name</td>
<td>Access</td>
<td>Modify</td>
</tr>
</thead>
<?php foreach ($controllers as $controller) {?>
<tbody>
<tr>
<td>
<?php echo ucfirst(str_replace("_"," ", $controller));?>
<input type="hidden" name="controller[]" value="<?php echo $controller;?>" />
</td>
<td>
<select name="access" class="form-control">
<option value="0">Disabled</option>
<option value="1">Enabled</option>
</select>
</td>
<td>
<select name="modify" class="form-control">
<option value="0">Disabled</option>
<option value="1">Enabled</option>
</select>
</td>
</tr>
</tbody>
<?php } ?>
</table>
<?php echo form_close();?>
</div>
</div>
</div><!-- # Page Inner End -->
</div><!-- # Page End -->
</div><!-- # Wrapper End -->
<?php echo Modules::run('admin/common/footer/index');?>
Your view file seems has access and modify option for each controller. But your input name is same.So the value of $access and $modify is the last input value. You can solve this way.Give access and modify input name as array
<select name="access[]" class="form-control">
...
<select name="modify[]" class="form-control">
Now your model
$name = $this->input->post('name');
$controllers = $this->input->post('controller');
$accesses = $this->input->post('access');
$modifies = $this->input->post('modify');
for($i=0;$i<count($controllers);$i++) {
$data = array(
'name' => strtolower($name),
'controller' => $controllers[$i],
'access' => $accesses[$i],
'modify' => $modifies[$i]
);
$this->db->insert($this->db->dbprefix . 'user_group', $data);
}
Hope you understand and solves your problem