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

Вопросы по вёрстке и JavaScript
Ответить
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 КБ) 8874 просмотра
Изображение
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" });
        }); 
Очень удобно. И само может значение по умолчанию подставлять.
может кому пригодится...
Ответить