Связанные динамичные списки Select

Вопросы по вёрстке и JavaScript
Ответить
spektr08
Сообщения: 88
Зарегистрирован: 2012.08.13, 15:36

Связанные динамичные списки Select

Сообщение spektr08 »

Всем привет!У меня вопрос как сделать связанные динамичные списки Select на yii?
Изображение
Nafania
Сообщения: 1227
Зарегистрирован: 2011.01.31, 13:12

Re: Связанные динамичные списки Select

Сообщение Nafania »

Тут тем 5 уже по этому поводу. Поищите.
spektr08
Сообщения: 88
Зарегистрирован: 2012.08.13, 15:36

Re: Связанные динамичные списки Select

Сообщение spektr08 »

Поискал на форуме нечего полезного так и не нашел(
В вюз делаю так

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

    <?php echo $form->dropDownList($model,'vechicle_type', $DropdownsArr['vechicle'], array(
'ajax' => array(
'type'=>'POST', //request type
'url'=>CController::createUrl('posts/create'), //url to call.
//Style: CController::createUrl('currentController/methodToCall')
'update'=>'#brand', //selector to update
 'dataType'=>'json',
'data'=>array('idProvince'=>'js:this.value'), 
это первый список марок марок машин

Как а дальше в контролере я не знаю что писать тут я получаю ид марки машины в контролере мне нужно с базы вытянуть список моделей машин этой марки
типа так

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

$res = Yii::app()->db->createCommand()
->select('id' , ' models')
->from(models)
->order(id ASC )
->were('id'  ) //получаемый ид
->queryAll(false);
 
Изображение
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

Доброго дня!
Разрешите продолжить тему? Рецепт нашел, однако понравилось исполнение в комментариях, решил повторить.
Однако с небольшим условием, проект турестический, поэтому будет 4 ДропДауна (Страна/Область/Город/Отель).
Пример, приведу, модель User и попробую.

По порядку.
Моя форма,

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

    <?
        echo CHtml::dropDownList('country','', Country::allCountry(), // в модели создал медот
        array(
        'ajax'=>array(
          'type'=>'POST', 
          'dataType'=>'json',
          'data'=>array('color'=>'js: $(this).val()'),
          'url'=>CController::createUrl('user/dynamiccities'),
          'success'=>'function(data) {
             $("#dropdownA").html(data.dropdownA);
             $("#dropdownB").html(data.dropdownB);
             $("#dropdownB").html(data.dropdownС);
          }'
        ))); 
         
        //empty since it will be filled by the other dropdown
        echo CHtml::dropDownList('dropdownA','', array());
        echo CHtml::dropDownList('dropdownB','', array());
        echo CHtml::dropDownList('dropdownC','', array());
    ?>
Для первого выпадающего списка в модели Country, создал метод:

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

public static function allCountry()
    {
       return CHtml::listData(self::model()->findAll(), 'country_id', 'country_title');
    }
Далее, в UserController.php еще метод

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

    public function actionDynamiccities()
    {
        //$dataA = CHtml::listData(self::model()->findAll(), 'area_id', 'area_title');
        $dataA = Location::model()->findAll('area_country=:country', array(':country'=>(int) $_POST['country']));
        foreach($dataA as $value=>$name)
            $dropDownA .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);

 
        $dataB = Location::model()->findAll('city_area=:country', array(':country'=>(int) $_POST['country']));        // эти строчки не правельные
        foreach($dataB as $value=>$name)
            $dropDownB .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);
            
        $dataC = Location::model()->findAll('area_country=:country', array(':country'=>(int) $_POST['country']));        // эти строчки не правельные
        foreach($dataC as $value=>$name)
            $dropDownC .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);    
            
         
        // return data (JSON formatted)
        echo CJSON::encode(array(
          'dropDownA'=>$dropDownA,
          'dropDownB'=>$dropDownB,
          'dropDownC'=>$dropDownC 
          ));
    }
 
там где мы вытаскиваем DataB и DataC, я попал в ступор...

Вот мои таблицы в БД
Изображение Изображение

еще вопрос, в самой форме есть строка

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

'url'=>CController::createUrl('user/dynamiccities'),
 
вызов текущего контролера, она правильная?

Если кто поможет буду примного благодарен.
Yii знаю неделю, сильно прошу не ругаться!
Изображение
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

так продолжим, может кто глазком глянуть, не много передала в 2 селекта, думал может так легче понять.

в контроллер UserController.php вставил код,

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

    public function actionSomeAction() {  
        $countryId = (int) $_POST['User']['country'];  
           
        if (!$countryId) {  
            echo CJSON::encode(array(  
                'no'=>true  
            ));  
            Yii::app()->end();
              
        }
        
        $countryId = 219;  
        $data = self::model()->findAll('id_country=:id_country',   
                    array(':id_country'=>$countryId));  
        
        $data = CHtml::listData($data, 'id', 'region_name_ru');  
          
        $dropdownRegion = '';  
         
        foreach($data as $value => $name)  
        {  
            $dropdownMetro .= CHtml::tag('option', array('value' => $value), CHtml::encode($name), true);  
        }  
          
        echo CJSON::encode(array(  
            'dropdownRegion'=>$dropdownRegion  
        ));  
    }

еще прописал правила,

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

        public function accessRules()
        {
        return array(
            array('allow',
                'actions'=>array('index','view', 'create', 'update','delete','dynamiccities','index', 'admin','someaction'),
                'roles'=>array('role_admin'),
            ),
            array('deny',
                'users'=>array('*'),
            ),
        );
        }
ни и моя форма

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

    <div class="row">  
        <?php echo $form->labelEx($model,'country'); ?>  
        <?php echo $form->dropDownList($model,'country', Country::allCountry(),array('empty' => 'Выберите страну'),   
                array(  
                    'class' => 'width150', 'ajax' => array(  
                    'type'=>'POST',   
                    'dataType'=>'json',  
                    'url'=>Yii::app()->createAbsoluteUrl('User/SomeAction'),  
                    'success'=>'function(data) { 
                        if (data.dropdownRegion) { 
                            $("#region-block").show(); 
                            $("#User_region").html(data.dropdownRegion); 
                        } 
                        else { 
                            $("#region-block").hide(); 
                        } 
                    }',  
                ))); ?>  
        <?php 
        echo $form->error($model,'country'); ?>  
    </div>  
      
    <div class="row" id="region-block" style="display: none;">  
        <?php echo $form->labelEx($model,'region'); ?>  
        <?php echo $form->dropDownList($model,'region', array(), array('class' => 'width150px')); ?>  
        <?php echo $form->error($model,'region'); ?>  
    </div>  
что не так не представляю, уже... рецепт взял отсюда, monoray.ru/31-yii-tips-chapter-5
архитектура Бд во вложении.
еще кстати, просписал, в виджете

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

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'user-form',
    'htmlOptions'=>array(
        'name'=>'form2'
        ),
    // Please note: When you enable ajax validation, make sure the corresponding
    // controller action is handling ajax validation correctly.
    // There is a call to performAjaxValidation() commented in generated controller code.
    // See class documentation of CActiveForm for details on this.
    'enableAjaxValidation'=>true,
)); ?>
Вложения
07-10-2013 22-01-03.jpg
07-10-2013 22-01-03.jpg (162.68 КБ) 7690 просмотров
Изображение
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Связанные динамичные списки Select

Сообщение SiZE »

У тя там выше ошибка?

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

$("#dropdownA").html(data.dropdownA);
$("#dropdownB").html(data.dropdownB);
$("#dropdownB").html(data.dropdownС); // <- тут не?
 
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

лучше 2 вариант посмотри, первый вариант я пока не рассматриваю, там было 4 селекта, я запутался и броил его пока.
последний вариант на 2 селекта, Страна -> Регион - может так быстрее найду косяки.

может я чего забыл включить или прописать?!
Изображение
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Связанные динамичные списки Select

Сообщение SiZE »

asisdes писал(а):так продолжим, может кто глазком глянуть, не много передала в 2 селекта, думал может так легче понять.
Меня 80% сообщений на форуме ставит в тупик и я перестаю сосредоточенно думать :lol:
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

:lol: :lol: :D походу дела, я уже совсем устал вчера...
глаза замылились
Изображение
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

Может я пропустил что либо,
надо ли дополнительно подключать jquery библиотеки и прочие файлы.
Изображение
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

Доброго дня еще раз всем!
Понимаю тема заезжаная, всех уже достала... , но чета у меня не заводится, может кто помочь разобраться
Новый вариант моих НЕ РАБОЧИХ селектов.
По идеи 3 селекта: Страна / Регион / Город

Так по порядку: вот мои поля в БД:
страна: id_country | country_name_ru | country_name_en | title | ....
регион: id_region | id_country |region_name_ru | region_name_en |title | ...
города: id_city | id_region | id_country | city_name_ru | city_name_en | title | alias
==================================================================================================================
По идеи, пользователь указывает свой адрес, в модели создал функция allCountry(), которая будет заполнять наш первый "Список"

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

    public static function allCountry()
    {
        return CHtml::listData(self::model()->findAll(), 'id_country', 'country_name_ru');
    }
===================================================================================================================
Далее
1. На форме, указываю: 'enableAjaxValidation'=>true,
2. В контроллере UserController, подтверждаю права и включаю Валидацию Ajax в Update:

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

        public function accessRules()
        {
        return array(
            array('allow',
                'actions'=>array('index','view', 'create','profile', 'savecoords', 'update',
                         'delete','password','index', 'admin','updatedistricts', 'updatecities'),
                'roles'=>array('role_admin'),
            ),
            
            array('allow',
                'actions'=>array('index','view', 'create','profile', 'savecoords', 
                          'update','delete','password','index', 'admin','updatedistricts', 'updatecities'),
                'roles'=>array('role_user'),
            ),
            
            array('allow',
                'actions'=>array('updatedistricts', 'updatecities'),
                'roles'=>array('role_guest'),
            ),
            
            array('deny',
                'users'=>array('*'),
            ),
        );
        }

    /**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id the ID of the model to be updated
     */
    public function actionUpdate($id)
    {
        $model = $this->loadModel($id);

        // Uncomment the following line if AJAX validation is needed
        $this->performAjaxValidation($model);

        if(isset($_POST['User']))
        {
            $model->attributes = $_POST['User'];
            if($model->save())
                Yii::app()->user->setFlash('updateUser','Вы удачно обновили информацию');
                $this->redirect(array('update','id'=>$model->id));
        }
        $this->render('update',array(
            'model'=>$model,
        ));
    }


=========================================================================
так же в UserController вписываю функции,

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

    public function actionUpdateRegion()
    {
            //Region
            $data = Region::model()->findAll('id_country=:id_country', array(':id_country'=>(int) $_POST['id_country']));
            $data = CHtml::listData($data,'id_region','region_name_ru');
            $dropDownRegion = "<option value=''>Выберите регион</option>"; 
            foreach($data as $value=>$name)
                $dropDownRegion .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);
 
            //City
            $dropDownCity = "<option value='null'>Выберите город</option>";
 
            // return data (JSON formatted)
            echo CJSON::encode(array(
              'dropDownRegion'=>$dropDownRegion,
              'dropDownCity'=>$dropDownCity
            ));
    }
 
    public function actionUpdateCity()
    {
            $data = City::model()->findAll('id_region=:id_region', array(':id_region'=>(int) $_POST['id_region']));
            $data = CHtml::listData($data,'id_city','city_name_ru');
            echo "<option value=''>Выберите город</option>";
            foreach($data as $value=>$name)
                echo CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);
    }
=============================================================================================
Ну и конечно же, моя главная форма:

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

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'user-form',
    'htmlOptions'=>array(
        ),
    // Please note: When you enable ajax validation, make sure the corresponding
    // controller action is handling ajax validation correctly.
    // There is a call to performAjaxValidation() commented in generated controller code.
    // See class documentation of CActiveForm for details on this.
    'enableAjaxValidation'=>true,
)); ?>
    <p class="note">Fields with <span class="required">*</span> are required.</p>
    <?php echo $form->errorSummary($model); ?>
    <div class="row">
        <?php echo $form->labelEx($model,'web'); ?>
        <?php echo $form->textField($model,'web',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'web'); ?>
    </div>
            <?
            $country = (!$model->isNewRecord) ? $model->country : ''; //echo $model->country;
            echo CHtml::dropDownList('id_country',$country, Country::allCountry(),
                array(
                    'prompt'=>'Выберите страну', //Yii::t('default', 'Select a country'),
                    'ajax' => array(
                        'type'=>'POST',
                        'url'=>CController::createUrl('admin/user/updateRegion'), 
                        'dataType'=>'json',
                        'data'=>array(
                         'id_country'=>'js:this.value',
                         'id_region'=>(!$model->isNewRecord) ? $model->region : null,
                         'id_city'=>(!$model->isNewRecord) ? $model->city : null,  
                         // если редактируется запись - передадим текущее значение атрибута связанной модели
                            ),  
                        'success'=>'function(data) {
                            $("#id_region").html(data.dropDownRegion);
                            $("#id_city").html(data.dropDownCity);
                        }',
            ))); 
            $regionNow = (!$model->isNewRecord) ? $model->region : '';
            echo CHtml::dropDownList('id_region',$regionNow, array(),
                array(
                    'prompt'=>'Выберите область',
                    'ajax' => array(
                        'type'=>'POST', 
                        'url'=>CController::createUrl('admin/user/updateCity'), 
                        'update'=>'#id_city', 
                        'data'=>array('id_region'=>'js:this.value'),
            ))); 
            
            $cityNow = (!$model->isNewRecord) ? $model->city : '';
            echo CHtml::dropDownList('id_city',$cityNow, array(), array('prompt'=>'Вы берите город'));
            ?>
=================================================================
вот результат в браузере, если вдруг там с якорями ошибка могла забрести,

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


<select name="id_country" id="id_country">
<option value="">Выберите страну</option>
<option value="219">Россия</option>
<option value="220" selected="selected">Украина</option> 
<option value="221">Беларусь</option>
.................
<option value="434">Южная Корея</option>
<option value="435">Южная Осетия</option>
<option value="436">Ямайка</option>
<option value="437">Япония</option>
<option value="438">Макао</option>
</select><select name="id_region" id="id_region">
<option value="">Выберите область</option>
</select><select name="id_city" id="id_city">
<option value="">Вы берите город</option>
</select>
 
Так а теперь по порядку вопросы и замечания где я мог налажать.
1.

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

      'url'=>CController::createUrl('admin/user/updateRegion'),  // Здесь у меня Админ панель идет как Модуль, поэтому добавилять "admin" в путь надо?!  
Здесь у меня "Админ панель" идет как Модуль, поэтому добавилять "admin" в путь надо?! т.е. может что то я с путями перепутал?!

2.

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

$data = Region::model()->findAll('id_country=:id_country', array(':id_country'=>(int) $_POST['id_country']));
Где-то проскальзывало, что надо писать, так в конце: $_POST['User']['id_country']));

Все я в тупике!
Вложения
Вот и форда!!!
Вот и форда!!!
морда.jpg (80.59 КБ) 8870 просмотров
Изображение
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

_
Последний раз редактировалось asisdes 2013.10.27, 11:47, всего редактировалось 1 раз.
Изображение
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

Доброго дня еще раз!

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

   <div class="row">
    <?
            $country = (!$model->isNewRecord) ? $model->country : ''; //echo $model->country;
            echo CHtml::dropDownList('id_country',$country, Country::allCountry(),
                array(
                    'prompt'=>'Выберите страну', //Yii::t('default', 'Select a country'),
                    'ajax' => array(
                        'type'=>'POST',
                        'url'=>CController::createUrl('user/updateregion'), 
                        'dataType'=>'json',
                        'data'=>array(
                         'id_country'=>'js:this.value',
                         'id_region'=>(!$model->isNewRecord) ? $model->region : null,
                         'id_city'=>(!$model->isNewRecord) ? $model->city : null,  
                         // если редактируется запись - передадим текущее значение атрибута связанной модели
                            ),  
                        'success'=>'function(data) {
                            $("#id_region").html(data.dropDownRegion);
                            $("#id_city").html(data.dropDownCity);
                        }',
            )));
            echo "<br />"; 
            $regionNow = (!$model->isNewRecord) ? $model->region : '';
            echo CHtml::dropDownList('id_region',$regionNow, array(),
                array(
                    'prompt'=>'Выберите регион',
                    'ajax' => array(
                        'type'=>'POST', 
                        'url'=>CController::createUrl('user/updatecity'), 
                        'update'=>'#id_city', 
                        'data'=>array('id_region'=>'js:this.value'),
            ))); 
            echo "<br />";
            $cityNow = (!$model->isNewRecord) ? $model->city : '';
            echo CHtml::dropDownList('id_city',$cityNow, array(), array('prompt'=>'Выберите город'));
            echo "<br />";
            ?>
    </div>
можно ли как то модифицировать что бы подгружалось, то что бы выбрано ранее,
т.е. например: Я уже выбрал и сохранился, а на следующий день редактирую еще раз, так вот ранее выбраное как подгружать?
в Странах, строка работает, подгружает мою страну, а вот в регионах и городах, всегда пусто и надо дернуть Страну что бы действие произошло.
У кого то подглядел код, но он не пашет кажись:

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

$cityNow = (!$model->isNewRecord) ? $model->city : '';
            echo CHtml::dropDownList('id_city',$cityNow, array(), array('prompt'=>'Выберите город'));
 
Изображение
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Связанные динамичные списки Select

Сообщение vova07 »

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

if ($model->isNewRecord) {
    $cityNow = '';
    $cityArray = array();
} else {
  $cityNow = $model->city;
  $cityArray = City::AllCity();
}
echo CHtml::dropDownList('id_city',$cityNow, $cityArray, array('prompt'=>'Выберите город')); 
asisdes
Сообщения: 202
Зарегистрирован: 2013.10.03, 15:54

Re: Связанные динамичные списки Select

Сообщение asisdes »

vova07, жаль нельзя вам в репу "+"!
Сработало!!!
Изображение
Аватара пользователя
mistbow
Сообщения: 64
Зарегистрирован: 2013.11.05, 20:26
Контактная информация:

Re: Связанные динамичные списки Select

Сообщение mistbow »

Я сделал так. Правда это пока не на yii, но реализовать PHP часть в контроллере на yii, думаю, не сложно.
JS:

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

(function ($, window, document, undefined) {
    $.fn.jCombo = function(url, opt) {        
        var defaults = {
                parent: null,
                first_optval : "0",
                selected_value : "0",
                initial_text: "-- Сделайте выбор --",
                method: "GET",
                dataType: "jsonp"                                
        };                
        var opt = $.extend( defaults, opt) ;
        var obj = $(this);
        if(opt.parent!=null) {
            var $parent = $(opt.parent);            
            $parent.removeAttr("disabled","disabled");
            $parent.bind('change',  function(e) {
                obj.attr("disabled","disabled");
                if($(this).val()!=opt.first_optval) obj.removeAttr("disabled");
                __render(    obj, { 
                    url: url, 
                    id: $(this).val(),
                    first_optval: opt.first_optval, 
                    initext: opt.initial_text, 
                    inival: opt.selected_value,
                    method: opt.method,
                    dataType: opt.dataType
                });
            });
        } else __render(obj,{ 
            url: url,
            id: "",
            first_optval: opt.first_optval,
            initext: opt.initial_text,
            inival: opt.selected_value,
            method: opt.method,
            dataType: opt.dataType
        });                    
        function __render($obj,$options) {            
            if($options.id==null) return false;
            $.ajax({
                type: $options.method,
                dataType: $options.dataType,                    
                url: $options.url + $options.id,
                success: function(data){
                    var response = '<option value="' + $options.first_optval + '">' + $options.initext + '</option>';
                    var selected;
                    for(var index in data.items) {
                        selected = (index==data['default_id'])?' selected="selected"':'';
                        response += '<option value="' + index + '"' + selected + '>' + data.items[index] + '</option>';
                    }
                    $obj.html(response);                                                                       
                    $obj.trigger("change");
                }
            });                    
        }
    }
})( jQuery, window, document ); 
И на php что-то типа...

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

<?php
session_start();
include_once("../../config.php");
include_once("../../dbconnect.php");

$db = GODB::getDB('main');
$db->setDebug(false);
// Get parameters from Array
$id = !empty($_GET['id']) ? intval($_GET['id']) : 0;

$sql = "SELECT DISTINCT t1.`complex_id`, t1.`complex_name` FROM ?t AS t1";
$sql .= " INNER JOIN ?t AS t2 ON t1.`complex_id` = t2.`complex_id`";
$sql .= " INNER JOIN ?t AS t3 ON t3.`complex_id` = t2.`complex_id`";
$sql .= " WHERE t2.`contractor_id` = '$id' AND t3.`uid` = '{$_SESSION['user_id']}' ORDER BY t1.`complex_id`";

$rows = $db->query($sql, ['complexes', 'complexes_permission', 'users_permissions'], 'row');
$items = array();
if (count($rows)) {
    foreach ($rows as $row) {
        $items[$row[0]] = $row[1];
    }
}
$data['default_id'] = (isset($_SESSION['complex_id'])) ? $_SESSION['complex_id'] : 0;
$data['items'] = $items;

//$_SESSION['contractor_id'] = $id;

header('content-type: application/json; charset=utf-8');
// convert into JSON format and print
$response = json_encode($data, JSON_UNESCAPED_UNICODE);
if (isset($_GET['callback'])) { //json padding
    echo $_GET['callback'] . "(" . $response . ")";
} else {
    echo $response;
} 
И на самой страничке подключается так:

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

$(function() {
            $("#contractor_id").jCombo("'.SERVER.DIR_SYSTEM.'helpers/getContractors.php", { selected_value : "0" } );
            $("#complex_id").jCombo("'.SERVER.DIR_SYSTEM.'helpers/getComplexes.php?id=", { parent: "#contractor_id" });
            $("#payments_id").jCombo("'.SERVER.DIR_SYSTEM.'helpers/getPayments.php?id=", { parent: "#contractor_id" });
        }); 
Очень удобно. И само может значение по умолчанию подставлять.
может кому пригодится...
Ответить