Slip
Slip

Reputation: 949

dependent dropdown yii2. How to do?

can I create a dependent dropdown in yii2?

I have two tables:

'id','name_country"
'id','name_city','country_id'

and have two methods in my model:

public function getCountryList()
{
$models = NetCountry::find()->asArray()->all();
return ArrayHelper::map($models, 'id', 'country_name');
} 

and

public function getCityList($parent_id) { 
$models = \common\models\City::find()->where(['parent_id' => $country_id])->asArray()->all();
return ArrayHelper::map($models, 'id', 'name_city','country_id');
}

I have the first field:

 <?= $form->field($model, 'country')->dropDownList($model->countryList),['id'=>'parent_id'];

and the second

<?= $form->field($model, 'city')->dropDownList($model->cityList);

I need to 'transmit' parent_id to controller and return city_list by AJAX (with JSON).

How can I do this? I saw an example in Yii1, but what about Yii2?

Upvotes: 4

Views: 27149

Answers (4)

You can do it without any widget manually:

make your activeform as follows:

<?=  $form->field($model, 'nameofyourmodel')->dropDownList(
    ArrayHelper::map(\app\models\nameofyourmodel::find()->all(), 'id', 'name'),
    [
        'prompt'=>'smth',
        'onchange' => '
            $.post(
                "' . Url::toRoute('getoperations') . '", 
                {id: $(this).val()}, 
                function(res){
                    $("#requester").html(res);
                }
            );
        ',

    ]
); ?>

and here the second form which receives the id from the first model:

 <?= $form->field($model,'nameofyourmodel')->dropDownList(
    [],
    [
        'prompt' => 'smth',
        'id' => 'requester'
    ]
); ?>

and the last action is to make a functionality in controller to match 2 ids and send them to your model:

public function actionGetoperations()
{
    if ($id = Yii::$app->request->post('id')) {
        $operationPosts = \app\models\firstmodel::find()
            ->where(['id' => $id])
            ->count();

        if ($operationPosts > 0) {
            $operations = \app\models\secondmodel::find()
                ->where(['firstmodelid' => $id])
                ->all();
            foreach ($operations as $operation)
                echo "<option value='" . $operation->firstmodelid. "'>" . $operation->name . "</option>";
        } else
            echo "<option>-</option>";

    }
}

Upvotes: 2

sprytechies
sprytechies

Reputation: 317

creating dependent dropdown in yii2 without using any third party libraries is quite as simple as yii1. you have to try following code written below as per your requirements. use gii to create models,views, controller for respective tables.

suppose there r two table like country, city as u written. then write the following code into views file for one controller(like country):

         <?php
                    use yii\helpers\ArrayHelper;
                    use yii\widgets\ActiveForm;
                    ?>
               <div>
            <?php
     $dataCountry=ArrayHelper::map(\app\models\Country::find()->
     asArray()->all(),'id', 'name');    
                  $form = ActiveForm::begin();
                echo $form->field($model, 'id')->dropDownList($dataCountry, 
                                     ['prompt'=>'-Choose a Name-',
                                         'class'=>'adjust',
                          'onchange'=>'
             $.post("'.Yii::$app->urlManager->createUrl('city/lists?id=').
           '"+$(this).val(),function( data ) 
                   {
                              $( "select#city" ).html( data );
                            });
                        ']); 

                $dataPost=ArrayHelper::map(\app\models\City::find()->
                 asArray()->all(), 'id', 'city');
              echo $form->field($model, 'id')
                    ->dropDownList(
                        $dataPost,   
                         ['id'=>'city',
                             'class'=>'adjust'
                             ]
                    );
                 ActiveForm::end(); 
               ?>
            </div>

and after this in another controller for city write following code as:

 <?php

namespace app\controllers;

class CityController extends \yii\web\Controller
{
        public function actionLists($id)
      {
         //echo "<pre>";print_r($id);die;
         $countPosts = \app\models\City::find()
         ->where(['country_id' => $id])
         ->count();

         $posts = \app\models\City::find()
         ->where(['country_id' => $id])
         ->orderBy('id DESC')
         ->all();

         if($countPosts>0){
         foreach($posts as $post){

         echo "<option value='".$post->id."'>".$post->city."</option>";
         }
         }
         else{
         echo "<option>-</option>";
         }

 }
}

then run into url it works!

edit: fixed url construction. http requests will now work.

Upvotes: 8

Premjith
Premjith

Reputation: 163

The above code is not working properly. There is an error in the line

$.post("'.Yii::$app->urlManager->createUrl('city/lists&id=').'"+$(this).val(),function( data ) 

console shows the error : Not Found (#404): Unable to resolve the request: subcategory/lists&id=54

is there any solution for this my controller looks like below

public function actionLists($id)
      {
         $posts = SubCategory::find()
         ->where(['category_id' => $id])
         ->orderBy('id DESC')
         ->all();

         if($posts){
         foreach($posts as $post){

         echo "<option value='".$post->id."'>".$post->name."</option>";
         }
         }
         else{
         echo "<option>-</option>";
         }

    }

when i remove the id from the url and hard coded it in to controller it works properly.

I have find a solution for this please change your view as follows

 <?= $form->field($model, 'category_id')->dropDownList($data,['prompt'=>'-Choose a Category-',

                                                            'onchange'=>'
             $.get( "'.Url::toRoute('product/catlists').'", { id: $(this).val() } )
                            .done(function( data )
                   {
                              $( "select#product-sub_categoryid" ).html( data );
                            });
                        ']); ?> 

and controller like this

public function actionCatlists($id)
    {
        $mymodel = new Product ();
        $size = $mymodel->modelGetCategory ( 'product_sub_category',$id );
        if($size){
            echo '<option value="">Choose Sub category</option>';
            foreach($size as $post){
                echo "<option value='".$post['id']."'>".$post['name']."</option>";
            }
        }
        else{
            echo '<option value="0">Not Specified</option>';
        }

    }

don't forget to include this on your view

use yii\helpers\Url;

Upvotes: 0

Neophile
Neophile

Reputation: 1519

use the krajee extension for dependent drop down

Details is here Krejee dependent dropdown for yii2

or follow following instructions:

Install the extension via composer:

 $ php composer.phar require kartik-v/dependent-dropdown "dev-master"

In your view :

  use kartik\widgets\DepDrop;

// Normal parent select
echo $form->field($model, 'cat')->dropDownList($catList, ['id' => 'cat-id']);

// Dependent Dropdown
echo $form->field($model, 'subcat')->widget(DepDrop::classname(), [
    'options' => ['id' => 'subcat-id'],
    'pluginOptions' => [
        'depends' => ['cat-id'],
        'placeholder' => 'Select...',
        'url' => Url::to(['/site/subcat'])
    ]
]);

// THE CONTROLLER

public function actionSubcat() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
$out = self::getSubCatList($cat_id);
// the getSubCatList function will query the database based on the
// cat_id and return an array like below:
// [
// ['id'=>'<sub-cat-id-1>', 'name'=>'<sub-cat-name1>'],
// ['id'=>'<sub-cat_id_2>', 'name'=>'<sub-cat-name2>']
// ]
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}

Upvotes: 11

Related Questions