I used Yii2 multiple selection dropdown , it is working fine at create but not showing me selected values on update!
Form:
$form->field($model, 'categories[]')
->dropDownList($model->CategoryDropdown,
[
'multiple'=>'multiple'
'class'=>'chosen-select input-md required',
]
)->label("Add Categories");
Model:
public function getCategoryDropdown()
{
$listCategory = Category::find()->select('ID,name')
->where(['is_subcategory' => 'Yes'])
->andWhere(['status' => 'active','approved' => 'active'])
->all();
$list = ArrayHelper::map( $listCategory,'ID','name');
return $list;
}
Controller:
public function actionCreate(){
...
$model->categories = implode(",",$_POST['Company']['categories']);
...
return $this->render('create', [
'model' => $model,
]);
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
echo $model->categories; // 1,2,4,5 values already assigned
...
return $this->render('update', [
'model' => $model,
]);
}
Database:
1,2,4,5
How I can show multi selected values in dropdown when I update my recored?
all your code is ok just need echo your $form->...
echo $form->field($model, 'categories[]')
->dropDownList($model->CategoryDropdown,
[
'multiple'=>'multiple',
'class'=>'chosen-select input-md required',
]
)->label("Add Categories");
or use <?= ?> in view!
Here is solution:
Form
<?=
$form->field($model, 'categories')
->dropDownList($model->CategoryDropdown,
[
'class'=>'chosen-select input-md required',
'multiple'=>'multiple'
]
)->label("Add Categories");
?>
Controller:
public function actionCreate(){
...
$model->categories = implode(",",$_POST['Company']['categories']);
...
return $this->render('create', [
'model' => $model,
]);
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->categories = explode(',', $model->categories);
...
if($model->load(Yii::$app->request->post()))
{
$model->categories = implode(",",$_POST['Company']['categories']);
...
$model->save()
}
return $this->render('update', [
'model' => $model,
]);
}
I would highly recommend to use Select2 from krajee it has all the options that you might need, using multiple in dropDownList() will make you able to choose multiple values but by pressing and holding Ctrl and choosing which is not comfortable as choosing them using Select2.
They did an amazing job i highly recommend anyone with this problem to use it.
Please check the documentations.
https://demos.krajee.com/widget-details/select2
Related
I have a form with a CheckboxList generated through a model "Candidates" and I need to make a vote where the voter can select multiple candidates and record.
How do I 'pick up' the selected candidates and write to the votes table / model ??
Form "votos"
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'candidato_id')->checkboxList(ArrayHelper::map(Candidatos::find()->where(['status' => 1])->orderBy("nome ASC")->all(), 'id', 'nome')); ?>
<?= Html::activeHiddenInput($model, 'eleicao_id', ['value' => 1]) ?>
<?= Html::activeHiddenInput($model, 'cargo_id', ['value' => 1]) ?>
<?= Html::activeHiddenInput($model, 'urna_id', ['value' => 1]) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
Model "Votos"
namespace app\models;
use Yii;
class Votos extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'votos';
}
public function rules()
{
return [
[['eleicao_id', 'candidato_id', 'cargo_id', 'urna_id', 'data'], 'required'],
[['eleicao_id', 'candidato_id', 'cargo_id', 'urna_id'], 'integer'],
[['data'], 'safe'],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'eleicao_id' => 'Eleicao ID',
'candidato_id' => 'Candidato ID',
'cargo_id' => 'Cargo ID',
'urna_id' => 'Urna ID',
'data' => 'Data',
];
}
}
Controller "VotosControllers"
public function actionVotacao()
{
$model = new Votos();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('votacao', [
'model' => $model,
]);
}
Slightly unrelated, but if you haven't already I would strongly suggest making sure you have something like xdebug set up so you can quickly see what your code is doing as you make your changes. Being able to set breakpoints and see what your form has submitted can go a long way to helping you solve a problem like this on your own and the framework becomes less mysterious. With that out of the way, something like the following MIGHT help as far as the controller goes. There is other validation you would want to do as well I should add. Maybe the each validator which you can read up on here. For actionUpdate() you would need to look at deleting all the values that relate to the related id and re-populate with the new ones, checkout deleteAll. Hopefully I don't get smashed too hard for providing this solution which is not a drop in solution.
public function actionVotacao()
{
$model = new Votos();
if (Yii::$app->request->isPost) {
$model->load(Yii::$app->request->post());
if ($model->save()) {
// Save the checkbox values.
if (!empty(Yii::$app->request->post()['Votos']['XXXX'])) { // Your form should give you an idea of what the XXXX should be, xdebug is also your friend.
foreach (Yii::$app->request->post()['Votos']['XXXX'] as $candidato_id) {
$candidato = new Candidato();
$candidato->id = $candidato_id;
if (!$candidato->save()) print_r($candidato->errors);
}
}
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
}
I have two dropDownlist in index, when I select the submit button it will get action in controller, and it performs some operations and again render the index with gridview, but the Selected dropDownList become blank, how can I set the default in dropDownllist??
Any suggestion should be appreciatable...
this is my view
<div class="col-sm-12" align="center">
<?= $form->field($model, 'fk_int_payroll_month')->dropDownList(
ArrayHelper::map(TblPayrollMonth::find()->all(), 'pk_int_payroll_month_id','vchr_month'),
['prompt'=> 'Select...'])
?>
</div>
<div class="col-sm-12" align="center">
<?= $form->field($model, 'fk_int_payroll_year')->dropDownList(
ArrayHelper::map(TblPayrollYear::find()->all(), 'pk_int_payroll_year_id','year'),
['options' => [isset($_POST['fk_int_payroll_year'])?'fk_int_payroll_year':'' => ['Selected'=>true]]],
['prompt'=> 'Seect...'])
?>
</div>
this is my controller
public function actionDisplay()
{
$model = new TblPayroll();
if(Yii::$app->request->post()!=null)
{
$data = Yii::$app->request->post();
// var_dump($data);
// die;
$month = $data['TblPayroll']['fk_int_payroll_month'];
$year = $data['TblPayroll']['fk_int_payroll_year'];
/* Be careful with this! */
$dataProviderSearch = new ActiveDataProvider
([
'query' => TblPayroll::find()->where(['fk_int_payroll_month'=>$month, 'fk_int_payroll_year'=> $year]),
'pagination' => ['pageSize' => 5],
]);
if($dataProviderSearch)
{
return $this->render('index', [
'dataProviderSearch' => $dataProviderSearch,
'model' => $model,
]);
}
}
else{
return $this->render('index', ['model' => $model]);
}
when i select dropdown it will gott actionDisplay, and find the dataprovider, and then it again render to index, so that time how can i show default selected value in dropDownlist?
If you are using an activeRecord then in controllerAction you should assign to the $model->your_fiedl the value you need for default
else{
$model->fk_int_payroll_month = 3
return $this->render('index', ['model' => $model]);
}
if you don't are using an active record you could use
->dropDownList($yourlist ,$selection)
eg
->dropDownList(ArrayHelper::map(TblPayrollMonth::find()->all() ,3)
In the rules() of my RegisterForm model:
[ 'user_username', 'unique', 'targetClass' => 'app\models\User', 'message' => 'This username is already been taken.' ],
In my controller:
$model = new RegisterForm();
if ( $model->load( Yii::$app->request->post() ) ) {
if ( $user = $model->register() ) {
return $this->redirect( [ '/login' ] );
}
}
In RegisterForm:
public function register() {
$user = new User();
$user->user_firstname = $this->user_firstname;
$user->user_lastname = $this->user_lastname;
$user->user_username = $this->user_username;
$user->user_email = $this->user_email;
$user->setPassword( $this->user_password );
if ( !$user->validate() ) {
return null;
}
if ( $user->save() ) {
return $user;
}
return null;
}
Form:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field( $model, 'user_firstname' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_lastname' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_username' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_email' )->textInput( [ 'maxlength' => true ] ) ?>
<?= $form->field( $model, 'user_password' )->passwordInput() ?>
<?= $form->field( $model, 'user_password_repeat' )->passwordInput() ?>
<?= Html::submitButton( 'Register', [ 'class' => 'btn btn-primary', 'name' => 'register-button' ] ) ?>
<?php ActiveForm::end(); ?>
Yet when I enter a username that I know already exists, the error never comes up and the record tries to save, though I get: Integrity constraint violation: 1062 Duplicate entry ...
EDIT: if I add the unique rule to the User model itself the form will not submit if I input a username that exists, the errors just don't show up
Like I have suspected, you are not checking for unique user_username attribute in client side. The reason why it's not working it's because you are not sending Ajax requests to check the results from database. Unlike other rules, unique rule requires additional Ajax requests to server since it would be pretty bad thing if Javascript would retrieve all currently registered username and store somewhere in Client side.
To solve you problem, in form write something like this:
$form = ActiveForm::begin([
'enableAjaxValidation' => true,
'validationUrl' => [<URL HERE>],
]);
Now you have to create a method (action) in controller that returns validation (not just unique, all of them) back to ActiveForm. So it could be something like this:
public function actionAjaxValidation()
{
$post = Yii::$app->request->post();
$model = new YourClass();
if (!$model->load($post)) {
throw new HttpException(403, 'Cannot load model');
}
$array = ActiveForm::validate($model);
return json_encode($array);
}
I'm using yii2-widget-fileinput for an image uploading in a form.
When I click on upload or the create button I get Trying to get property of non-object error in controller.
Controller
public function actionCreate()
{
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/uploads/';
$model = new Ads();
$provinces = ArrayHelper::map(Province::find()->all(), 'name', 'name');
if ($model->load(Yii::$app->request->post())){
$image = UploadedFile::getInstances($model, 'image');
$model->filename = $image->name;
$ext = end((explode(".", $image->name)));
$avatar = Yii::$app->security->generateRandomString().".{$ext}";
$path = Yii::$app->params['uploadPath'].$avatar;
if ($model->save()) {
$image->saveAs($path);
$model->image_adr = $path;
return $this->redirect(['view', 'id' => $model->id]);
}else{
echo "error on saving the model";
}
}
return $this->render('create', [
'model' => $model,
'provinces'=>$provinces,
]);
}
model rules
public function rules()
{
return [
[['type', 'explanation', 'cost', 'province_name', 'address'], 'required'],
[['type', 'explanation', 'image_adr', 'address'], 'string'],
[['cost'], 'integer'],
[['province_name'], 'string', 'max' => 20],
[['province_name'], 'exist', 'skipOnError' => true, 'targetClass' => Province::className(), 'targetAttribute' => ['province_name' => 'name']],
[['image'],'safe'],
[['image'], 'file', 'extensions'=>'jpg, gif, png', 'maxFiles'=>3,],
];
and finnally the view
<?= $form->field($model, 'image[]')->widget(FileInput::classname(), [
'options'=>['accept'=>'image/*', 'multiple'=>true],
'pluginOptions'=>['allowedFileExtensions'=>['jpg','gif','png'], 'overwriteInitial'=>false,]
]); ?>
the problem should refer to this part in the controller I think
$image = UploadedFile::getInstances($model, 'image');
An image of the error might be helpful
You should check first is image in post or not.
....
$image = UploadedFile::getInstances($model, 'image'); //getInstanceByName
if (!empty($image))
$model->filename = $image->name;
.....
if ($model->save()) {
if (!empty($image))
$image->saveAs($path);
.........
Make sure in your form ency type is added:
$form = ActiveForm::begin([
'id' => 'form_id',
'options' => [
'class' => 'form_class',
'enctype' => 'multipart/form-data',
],
]);
The problem is when you're using UploadedFile::getInstances($model, 'image'); you should work with foreach or treat it like an array.
Something that made me a problem was that even if you're using UploadedFile::getInstanc (notice the obsoleted s in the end) you should still treat it like an array and in all parts you should use $image[0], not $iamge lonely.
renderPartial clientSide validation doesn't work. I want to render part of form with ajax. Ex.:
_form.php
$form = ActiveForm::begin([
'options' => [
'enableAjaxValidation' => true,
]
]);
$form->field($model, 'category_id')->dropDownList($category, [
'onchange'=>'
$.get( "'.Url::toRoute('/controller/params').'", { id: $(this).val() } )
.done(function( data ) {
$( "#offers-param-content" ).html( data );
}
);'
]);
Controller.php
public function actionParams($id)
{
$model = new Param();
$params = EavAttribute::find()->where(['category_id'=>$id])->all();
$this->renderPartial('_params', ['model' => $model, 'params' => $params];
}
_params.php
foreach($params as $item){
echo Html::activeTextInput('text', $model, $item->name);
}
If you want to enable client validation, then set this property to true.
$form = ActiveForm::begin([
'options' => [
'enableAjaxValidation' => true,
'enableClientValidation'=>true
]
]);
And use renderAjax() function in place of renderPartial() it will inject into the rendering result with JS/CSS scripts and files which are registered with the view
In your Controller.php you need to set layout to false and die the execution
public function actionParams($id)
{
$this->layout = false;
$model = new Param();
$params = EavAttribute::find()->where(['category_id'=>$id])->all();
$this->renderPartial('_params', ['model' => $model, 'params' => $params];
die;
}
Your not returning any validation errors from your controller to your view.
To archive that use
yii\widgets\ActiveForm::validate($yourModel);
If your not using activeform you can return errors by
$model->getErrors();//will return errors from $model->validate()
From your excerpt try this
public function actionParams($id) {
$model = new Param();
if ($model->load(Yii::$app->request->post())) {
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model); /* Validation error messages are returned by this static function */
}
$params = EavAttribute::find()->where(['category_id' => $id])->all();
$this->renderPartial('_params', ['model' => $model, 'params' => $params]);
}
}