DepDrop preselected value

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

DepDrop preselected value

Сообщение surrealistic_pillow »

Для вывода зависимых селектов использую DepDrop, вывожу их в ActiveForm в _search.php для фильтрации списка слушателей.
Соответственно, селект Организация формируется в зависимости от выбранных option в родительских селектах Муниципалитет и Тип ОО.
Все работает и список слушателей фильтруется как надо. Но после нажатия кнопки Search сбрасывается значение последнего селекта. Иначе говоря, ни один из option не явлется selected
Изображение
Как мне сохранять выбранное перед фильтрацией значение этого селекта?
В модели Student

Код: Выделить всё

    public function getOrgsList($area_id, $org_type_id){
        $orgs_query = Orgs::find()
            ->select(['id', 'org_name'])->where(['area_id'=>$area_id, 'org_type_id'=>$org_type_id])
            ->distinct(true)
            ->all();
        $orgs = ArrayHelper::map($orgs_query, 'id', 'org_name');
        foreach($orgs as $key=>$org){
            $id = $key;
            $name = $org;
            $orgArr[] = ['id'=>$id,'name'=>$name];
        }
        $finalArr = ['out' => $orgArr,'selected'=>''];
        return $finalArr;
    }
контроллер StudentController

Код: Выделить всё

    public function actionOrg() {
        $out = [];
        if (isset($_POST['depdrop_parents'])) {
            $ids = $_POST['depdrop_parents'];
            $area_id = empty($ids[0]) ? null : $ids[0];
            $org_type_id = empty($ids[1]) ? null : $ids[1];
            if ($area_id != null) {
               $data = Student::getOrgsList($area_id, $org_type_id);
                /**
                 * the getProdList function will query the database based on the
                 * cat_id and sub_cat_id and return an array like below:
                 *  [
                 *      'out'=>[
                 *          ['id'=>'<prod-id-1>', 'name'=>'<prod-name1>'],
                 *          ['id'=>'<prod_id_2>', 'name'=>'<prod-name2>']
                 *       ],
                 *       'selected'=>'<prod-id-1>'
                 *  ]
                 */
               
               echo Json::encode(['output'=>$data['out'], $data['selected']]);
               return;
            }
        }
        echo Json::encode(['output'=>'', 'selected'=>$data['selected']]);
    }
/views/student/_search.php

Код: Выделить всё

// Dependent Dropdown
echo $form->field($model, 'org_id')->widget(DepDrop::classname(), [
     'options' => ['id'=>'org-id'],
     'pluginOptions'=>[
         'depends'=>['area-id','orgtype-id'],
         'placeholder' => '',
         'url' => Url::to(['/student/org']),
         'loading' => false,
         'initialize' => true
     ],
 ]);
Когда в модели вставляю id вручную

Код: Выделить всё

$finalArr = ['out' => $orgArr,'selected'=>192];
Все равно значение селекта после фильтрации сбрасывается
Уже глаза и руки устали гуглить. Думаю, решение лежит где-то на поверхности. Подскажите, кто-нибудь

surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

Re: DepDrop preselected value

Сообщение surrealistic_pillow »

Ни у кого похожих проблем не было?

В документации написано про default value. То есть после обновления страницы должно подставляться некое дефолтное значение в селект. Но это совсем не то что нужно. Ведь элементарная логика подсказывает, что значения в фильтре после фильтрации должны сохраняться, чтобы пользователь, который отфильтровал список, видел, какие именно фильтры были применены.

Хотя бы скажите, как должно быть по умолчанию. После обновления страницы значение дочернего селекта должно сохранятся, или DepDrop по умолчанию этого не предусматривает?

Было бы неплохо увидеть чей-нибудь рабочий код взаимозависимых селектов реализованных с помощью DepDrop

Loveorigami
Сообщения: 975
Зарегистрирован: 2014.08.27, 21:54

Re: DepDrop preselected value

Сообщение Loveorigami »

Делал на днях зависимый список с DepDrop в админке для ActionCreate в 2 уровня.
Основному списку присваивал значение, условно

Код: Выделить всё

$this->select1_id = Yii:$app->request->get('select1_id');
 
После чего ajax запрос идет уже сам на actionDepDrop и в нем подтягиваются нужные дочерние элементы.
сам action тут
https://github.com/loveorigami/lo-core/ ... epDrop.php
мало чем отличается от kartik-a
т.е. мы тут получаем селект, зависимый от первого.

Чтобы во втором селекте выделился нужный пункт, этот атрибут также должен быть определен ДО инициализации виджета, т.е. рядом с select1_id

Код: Выделить всё

$this->select1_id = Yii:$app->request->get('select1_id');
$this->select2_id = Yii:$app->request->get('select2_id');
 
у меня так. Все работает и выделяется

У вас же может быть значение второго атрибута не проходит валидацию и равно 0

surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

Re: DepDrop preselected value

Сообщение surrealistic_pillow »

До сих пор проблема не решена.
Перед инициализацией виджета в _search.php

Код: Выделить всё

<?var_dump($model->org_id);?>
,после выбора опшионов во всех селекатх и применения фильтра
выводит, к примеру,
string(3) "173"
. То есть id пункта в селекте организаций, выбранного перед применением фильтра.
До применения фильтра, соответственно, NULL.

Так вот, если свойство $model->org_id имеет значение string(3) "173", раззве не должен option с этим значением автоматом становится selected??
У вас же может быть значение второго атрибута не проходит валидацию и равно 0
Но если бы валидацию значение не проходило, то фильтр бы не применялся, и поле подсвечивалось красным.

У меня же все фильтруется. Исходя из значений, примененных в фильтре (включая злополучный select с организзациями), формируется Gridview Но не ставится атрибут selected у нужного option

На всякий случай, вот rules() из StudentSearch

Код: Выделить всё

    public function rules()
    {
        return [
            [[id', 'user_id', 'program_id', 'period_id', 'edu_form_id', 'paymethod_id', 'region_id', 'area_id', 'org_type_id', 'org_id', 'paid'], 'integer'],
            [['user_id', 'fullname', 'post', 'category_id', 'edu_id', 'phone', 'email', 'password'], 'safe'],
        ];
    }
Пробовал прописывать в параметре options:

Код: Выделить всё

echo $form->field($model, 'org_id')->widget(DepDrop::classname(), 
    [
        'options' => ['id'=>'org-id', [$model->org_id=>["selected"=>true]]],
        'pluginOptions'=>[
            'initDepends'=>['area-id','orgtype-id'],
            'depends'=>['area-id','orgtype-id'],
            'placeholder' => '',
            'url' => Url::to(['/student/org']),
            'loading' => false,
        'initialize' => true
        ],
    ]);
Ничего не меняется, атрибут selected все так же не выводится

Loveorigami
Сообщения: 975
Зарегистрирован: 2014.08.27, 21:54

Re: DepDrop preselected value

Сообщение Loveorigami »

Ну, давайте попробуем разобраться поэтапно.
Откинем второй DepDrop. Попробуем установить selected на первый.
Итак, у меня
1. Родительский - это обычный select с html id=object_id в $params

Код: Выделить всё

echo $form->field($model, 'object_id')->dropDownList([$items,$params]);
 
2. Зависимый список. $model->object_id определен в контроллере (=10)

Код: Выделить всё

echo $form->field($model, 'room_id')->widget(DepDrop::className(), 
    [
        'options' => ['id'=>'room_id'],
        'data' => $model->getRoomsByObject($model->object_id) // видимо из-за этого у Вас не работает. Нельзя установить select к пустоте
        'pluginOptions'=>[
            'depends'=>['object_id'],
            'placeholder' => '',
            'url' => Url::to(['/object/rooms']),
        ],
    ]);
 
------------------------
Пока писал - увидел расхождения в настройках вашего и моего виджета.
У меня, если определен $model->object_id, тогда в data помещается список комнат. Я их через DepDrop не тяну. И больше никаких настроек.
У вас data - отсутствует
Последний раз редактировалось Loveorigami 2016.12.12, 13:57, всего редактировалось 3 раза.

Loveorigami
Сообщения: 975
Зарегистрирован: 2014.08.27, 21:54

Re: DepDrop preselected value

Сообщение Loveorigami »

+ я бы все равно проверил
у вас

Код: Выделить всё

[[id', 'user_id', 'program_id', 'period_id', 'edu_form_id', 'paymethod_id', 'region_id', 'area_id', 'org_type_id', 'org_id', 'paid'], 'integer'],
а получаете вы string

Код: Выделить всё

string(3) "173" 

surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

Re: DepDrop preselected value

Сообщение surrealistic_pillow »

Loveorigami, к сожалению, проблема сохраняется.
вызов виджета переделал по вашему примеру

Код: Выделить всё

echo $form->field($model, 'org_id')->widget(DepDrop::classname(), 
    [
        'options' => [
            'id'=>'org-id', 
            [$model->org_id=>["selected"=>true]],             
        ],
        'data'=>$model->getOrgsList($model->area_id, $model->org_type_id),
        'pluginOptions'=>[
            
            'initDepends'=>['area-id','orgtype-id'],
            'depends'=>['area-id','orgtype-id'],
            'placeholder' => '',
            'url' => Url::to(['/student/org']),
            'loading' => false,
            'initialize' => true
        ],
        //'type' => DepDrop::TYPE_SELECT2,
    ]); 
$model->org_id привел к типу integer перед инициализацией виджета

Код: Выделить всё

<?$model->org_id = (int)$model->org_id;?>
вот, кстати как этот злополучный селект выводится в браузере

Код: Выделить всё

<select id="org-id" class="form-control" name="StudentSearch[org_id]" 0-311="{"selected":true}" data-krajee-depdrop="depdrop_af277980">
   <option value=""></option>
   <option value="311">ГПОУ "УМК"</option>
   <option value="885">ПОУ "УПК"</option>
</select>
А можно посмотреть код вашего метода getRoomsByObject? Может я както массив для списка неправильно формирую

surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

Re: DepDrop preselected value

Сообщение surrealistic_pillow »

Попробовал один из родительских селектов убрать. Оставил по принципу один родитель - один дочерний.
Все то же самое. Селект формируется, после фильтрации нет selected

Loveorigami
Сообщения: 975
Зарегистрирован: 2014.08.27, 21:54

Re: DepDrop preselected value

Сообщение Loveorigami »

А можно посмотреть код вашего метода getRoomsByObject? Может я както массив для списка неправильно формирую
Это условно.
А так, как обычно для селекта (не для Виджета!)

Код: Выделить всё

if($this->object_id){
$data = Rooms::find()->where(['object_id'=>$this->object_id])->asArray()->all();
return arrayHelper::map($data, 'id', 'name');
}
return [];
 
Что у меня в depDrop, гляну завтра, проект на локалке на работе.
============
вот, кстати как этот злополучный селект выводится в браузере
<select id="org-id" class="form-control" name="StudentSearch[org_id]" 0-311="{"selected":true}" data-krajee-depdrop="depdrop_af277980">
<option value=""></option>
<option value="311">ГПОУ "УМК"</option>
<option value="885">ПОУ "УПК"</option>
</select>
Вроде все верно, но чтобы селект был выбранным, у вас $this->org_id должен равняться 311.

Хотя похоже, это у Вас второй зависимый список. А мы еще не уверены, как работает первый. И работает ли?

============
Можно еще упростить.
1. Сделайте обычный список через dropDownList.
2. Определите вручную $org_id для построения дочернего списка.
3. Сделайте дочерний обычный список через dropDownList с заранее выбранными данными из $org_id (у меня getRoomsByObject, что потом подставляется в параметр data виджета)

Зайдя на index - мы должны получить два выбранных селекта, как будто это независимые списки.

Далее перейдем к depDrop)))

Loveorigami
Сообщения: 975
Зарегистрирован: 2014.08.27, 21:54

Re: DepDrop preselected value

Сообщение Loveorigami »

Пересмотрел еще раз конфигурацию виджета
http://demos.krajee.com/widget-details/ ... nced-usage

Ваш случай - №3.
Там в каждом селекте, который нужно сделать с заранее выбранной опцией selected - присутствует подготовленный массив data

Обратите внимание на

Код: Выделить всё

// Additional input fields passed as params to the child dropdown's pluginOptions
echo Html::hiddenInput('input-type-1', 'Additional value 1', ['id'=>'input-type-1']);
echo Html::hiddenInput('input-type-2', 'Additional value 2', ['id'=>'input-type-2']); 

surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

Re: DepDrop preselected value

Сообщение surrealistic_pillow »

Третий случай вашей ссылке рассматривает 4 уровня селектов. И там получается, что все зависят друг от друга, то есть второй от первого, третий от второго и первого, четвертый от третьего, второго и первого.

Мой случай проще.
У меня три селекта. И только последний зависимый. Подробнее:
Муниципалитет - обычный список, для него выбираются все строки из таблицы area (вывожу его обычным dropDownlist)
Тип образовательной организации - обычный список, все строки из таблицы org_type (вывожу его обычным dropDownlist)
Образовательная организация - зависимый селект, зависит от двух предыдущих селектов. Для его построения из таблицы org (в таблице есть поля area_id и org_type_id) выбираются те строки, которые соответствуют условию area_id = $model->area_id и org_type_id= $model->org_type_id. Выводится виджетом DepDrop от kartik.

То есть, если не выбран муниципалитет или тип ОО, список организаций не строится, если выбраны оба, то список формируется.
И мне нужно, чтобы обновление списка организаций происходило на лету, без перезагрузки страницы.
Когда я вывожу селект таким вот обычным образом

Код: Выделить всё

<?=$form->field($model, 'org_id')->dropDownlist($model->getOrg($model->area_id, $model->org_type_id),['prompt'=>'', 'id'=>'org-id', ]);
Для этого используя метод в модели

Код: Выделить всё

    public function getOrgList($area_id,$org_type_id){
        $orgs_query = Orgs::find()
            ->select(['id', 'org_name'])->where(['area_id'=>$area_id, 'org_type_id'=>$org_type_id])
            ->distinct(true)
            ->all();
        $orgs = ArrayHelper::map($orgs_query, 'id', 'org_name');
        return $orgs;
    }
То список формируется, после перезагрузки страницы:
Я выбираю из списка муниципалитет, выбираю из списка тип ОО и нажимаю Поиск, страница перезагружается, выбранные до этого значения в селектах муниципалитет и тип ОО сохраняются, селект организаций сформирован. Выбираю нужную организацию из этого списка, нажимаю Поиск еще раз - выбранная в списке организация остается selected.
Вроде все верно, но чтобы селект был выбранным, у вас $this->org_id должен равняться 311
перед кодом виджета в _search.php

Код: Выделить всё

<?
var_dump($model->org_id);?>
после перезагрузки страницы выводит 311, когда выбран именно option с value=311

surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

Re: DepDrop preselected value

Сообщение surrealistic_pillow »

Вобщем, после нескольких дней мозголомки я отказался от DepDrop, сделал своими силами таким образом:
Селекты муниципалитет и тип ОО вывожу вот так

Код: Выделить всё

<?=$form->field($model, 'area_id')->dropDownlist(
            ArrayHelper::map(Area::find()->all(), 'id', 'area_name'),
            [
                'prompt'=>'', 
                 'id'=>'area-id',
                'onchange'=>
                    '$.post("index.php?r=student/org&area_id='.'"+$(this).val()+"&org_type_id="+$("#orgtype-id").val(), function(data){
                        $("#org-id").empty();
                        $("#org-id").html(data);
                    });'
            ]
        );?>
И соответственно в actionOrg в контроллере принимаю area_id и org_type_id, делаю запрос к БД и возвращаю список опшионов.
После фильтрации, выбранное значение становится selected.
Единственно, что меня заинтересовало в DepDrop - TYPE_SELECT2, селект с текстовым полем, жаль что не получилось разобратсья

Loveorigami
Сообщения: 975
Зарегистрирован: 2014.08.27, 21:54

Re: DepDrop preselected value

Сообщение Loveorigami »

На этом этапе все верно.
Ошибка заключается в том, что после перезагрузки фильтра старое значение DepDrop остается selected.
1. У вас нет расширенного фильтра на странице? Иначе оно может заменять первое попавшееся на странице по ID.
2. Думаем дальше. Перечитал тему. У вас getOrgList - метод, который в начале доставал массив depdrop, а теперь - массив для dropdown.
Должно быть
- getOrgList - массив для dropdown, который инициализируется в data виджета
- getOrgListDepDrop - ваш первоначальный массив, который получается через ajax с опцией selected.
- в action 'url' => Url::to(['/student/org']), убеждаемся в консоли или в дебаг панели, что после изменения организации приходят верные значения

Код: Выделить всё

 $ids = $_POST['depdrop_parents'];
            $area_id = empty($ids[0]) ? null : $ids[0];
            $org_type_id = empty($ids[1]) ? null : $ids[1];
             
В вашем случае $area_id и $org_type_id должны содержать некие значения.
И в финале обязательно - $data['selected'] = $org_type_id

Райымбек
Сообщения: 6
Зарегистрирован: 2019.12.23, 15:38

Re: DepDrop preselected value

Сообщение Райымбек »

Сегодня столкнулся с такой же задачей. Решил следующим образом, и даже Select2 получилось прикрутить. Хоть и запоздало, может кому-то будет интересно) Если у кого-то есть идеи по улучшению кода, пожалуйста, напишите.

Код формы:

Код: Выделить всё

 
<?= $form->field($model, 'priority_id')
        ->dropDownList(Priority::find()->select(['name', 'id'])->indexBy('id')->column(),
            [
                'prompt' => Yii::t('app', 'Priority'),
                'id' => 'priority_id'
            ])->label(false) ?>

<?= $form->field($model, 'indicator_id')->widget(DepDrop::className(), [
        'type' => DepDrop::TYPE_SELECT2,
        'options' => [
            'id' => 'indicator_id',
            'placeholder' => Yii::t('app', 'Indicator')
        ],
        'select2Options' => [
                'pluginOptions' => ['allowClear' => true]
        ],
        'pluginOptions' => [
            'depends' => ['priority_id'],
            'url' => Url::to(['/indicator/list-ajax']),
            'params' => ['indicator_id' => $model->indicator_id],
            'initialize' => true,
        ]
    ])->label(false) ?>          
Код контроллера:

Код: Выделить всё

public function actionListAjax()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        if($priority_id = Yii::$app->request->post('depdrop_parents')[0]){

            $output = Indicator::find()
                ->select(['id', 'name'])
                ->where(['priority_id' => $priority_id])
                ->asArray()
                ->all();

            $selected = '';

            if($key = Yii::$app->request->post('depdrop_params')['indicator_id']){

                $selected = (key_exists($key, ArrayHelper::map($output, 'id', 'name'))) ?: $key;

            }

            return ['output' => $output, 'selected' => $selected];
        }

        return ['output' => '', 'selected' => ''];
    }

Ответить