"By Example" : CHtml - dropDownList()
Рубрика: Перевод Cookbook
12 Окт. 2009
Серия рецентов "By Example" пытается предоставить для разработчиков примеры использования самых распостраненных действий в Yii. Учимся использовать CHtml::dropDownList() на примерах!
CHtml::dropDownList() method
public static function dropDownList($name,$select,$data,$htmlOptions=array())
Генерируем выпадающий список (dropdown list)
$name - Название для нашего элемента (значение name для тега)
$select - Выбранный элемент по умолчанию (из $data)
$data - Массив типа "$ключ => $значение"
$htmlOptions - Другие html атрибуты
Пример 1: Создаем простой список выбора пола (мужской,женский)
<?php echo CHtml::dropDownList('listname', $select,
array('M' => 'Male', 'F' => 'Female'));
Результат:
<select id="listname" name="listname">
<option value="M">Male</option>
<option value="F">Female</option>
</select>
Пример 2: Создаем простой список с пустым первым элементом
<?php echo CHtml::dropDownList('listname', $select,
array('M' => 'Male', 'F' => 'Female'),
array('empty' => '(Select a gender'));
Результат:
<select id="listname" name="listname">
<option value="">(Select a gender</option>
<option value="M">Male</option>
<option value="F">Female</option>
</select>
Пример 3: Передаем данные для заполнения списка из модели
Сначала вы генерируете данные для списка внутри модели, а затем передаете их в отображение!
Модель:
public function getGenderOptions(){
return array('M' => 'Male', 'F' => 'Female');
}
Отображение:
<?php echo CHtml::dropDownList('listname', $select,
$model->genderOptions,
array('empty' => '(Select a gender'));
Пример 4: Заполняем данными из базы
Для того чтобы создать список с данными из базы, вы должны использовать listData для перевода их к формату "$ключ=>$значение"
Модель:
// делаем выборку всех категорий из баззы данных
$models = categories::model()->findAll(
array('order' => 'category_name'));
// при помощи listData создаем массив вида $ключ=>$значение
$list = CHtml::listData($models,
'category_id', 'category_name');
Теперь мы генерируем наш список используя данные из переменной $list:
<?php echo CHtml::dropDownList('categories', $category,
$list,
array('empty' => '(Select a category'));
- Оригинал "By Example: CHtml" [англ.]
Если хотите опубликовать этот материал у себя - пожалуйста, разместите ссылку на страницу откуда вы его взяли.
- Странно, каждый день по несколько раз посещаю официальный сайт Yii Фреймворка – и только сегодня заметил новость за 15е ... "Видео урок "Как создать свой блог""
- Долгожданный релиз 1.1.1 по праву можно назвать service pack к 1.1.0: исправлено более двадцати ошибок. Добавлено более тридцати улучшений и ... "Yii PHP framework 1.1.1 и 1.0.12"
- Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут ... "Урок 8 : Подключаем дизайн"

[guest] Гость
Было сказано: Пятница, 06 Ноябрь 2009
Было бы круто прожевать эту тему http://www.yiiframework.com/doc/cookbook/24/ Если можно с понятным для восприятия примером в разделе "Создаем блог вместе"

[adm] zolter
Было сказано: Пятница, 06 Ноябрь 2009
Могу перевести в раздел "Перевод Cookbook", но в раздел создания блога она не клеится ;)

[guest] Dima
Было сказано: Пятница, 06 Ноябрь 2009
Да в продолжение CHtml - dropDownList, будет как раз в тему. Только вот пример там какой-то нерабочий. Седня его ковырял. Если обычно через сабмит передавать параметр 1-го селекта то работает, а ajax нет.

[guest] Гость
Было сказано: Суббота, 07 Ноябрь 2009
вопрос не потеме немного)
А вот, если написал сайт на yii то надо писать в футоре что использовал данный frameWork? )

[guest] Dima
Было сказано: Воскресенье, 08 Ноябрь 2009
С примером все ок (cookbook/24), надобыло поместить в форму ;)
(beginForm приемер endForm)
Вообще ajax примеров маловато будет. Открой тему об ajax in yii.
Нубы хотят знать о зависимых селектах :) (2 и > пар селектов, как при постранич новигации выбранный селект оставить активным, как испльзовать данные с этих селектов при поиске в БД)
Для первых тем самое то!

[guest] Гость
Было сказано: Воскресенье, 10 Январь 2010
Все таки не понятно как использовать dropDownList для записи в базу данных.

[guest] Гость
Было сказано: Понедельник, 11 Январь 2010
Что значит "как использовать dropDownList для записи в базу данных"? - Как любое из полей в HTML форме!

[adm] zolter
Было сказано: Понедельник, 11 Январь 2010
> Все таки не понятно как использовать dropDownList для записи в базу данных.
Просто передаете в dropDownList экземпляр модели с которой работаете. И потом после того как форма посылается (нажимаете на субмит кнопку) - экшин получит данные в $_POST где и будет ваш дропдовнлист.

[guest] Гость
Было сказано: Понедельник, 11 Январь 2010
Список сгенерили, юзер что-то выбрал. А как получить результат того, что он выбрал в beforeValidate?

[adm] zolter
Было сказано: Понедельник, 11 Январь 2010
Вы можете сделать принтовку всего $_POST-а и увидеть что выбрал юзер:
echo "<pre>";
print_r($_POST);
Или же создайте, и заполните объект модели данными:
$form = new YouModel();
$form->attributes = $_POST['YouModel'];

[guest] Гость
Было сказано: Пятница, 05 Февраль 2010
А как сгенерировать ссылку в зависимости от того что чел выбрал?
Например мне надо сделать выборку языка:
чел выбрал английский, и мы перегрузили страничку с теми же параметрами GET только прибавили еще переменную lang.

[guest] Гость
Было сказано: Пятница, 05 Февраль 2010
не.. Вы не поняли.. надо событие прикрутить.
чтобы по селекту редирект отрабатывал без нажатий на кнопочки всякие.
А так:
Просто выбрал язык и страничка перегрузилась (без Button) Можно конечно и с Button но не красиво как то.
Событие нужно понимаете?
типа того как:
<select name="jumpMenu" id="jumpMenu" onchange="MM_jumpMenu('parent',this,0)">чтобы ы селдекте получилось

[guest] zolter
Было сказано: Суббота, 06 Февраль 2010
Ну я бы делал следующим образом.
1. ваш селект окружил в <form method="GET" action="текущий_урл_с_гетами_всеми">
2. кинул он-ченж к примеру с функцией test
3. создал тут же эту функцию которая просто делал б submit формы
получится что при выборе в выпадающем списке языка - селект заполнится нужным значением, а наша функция просто субмитнит форму на эту же страницу тем самым задав переменную $_get['lang'] к примеру.

[guest] Гость
Было сказано: Вторник, 09 Февраль 2010
Это то все понятно, похоже я не смог донести до Вас суть вопроса:)
мой код такой:
<?php echo CHtml::beginForm('','GET', array('class'=>'langform'));?>
<?php echo 'CHOOSE LANGUAGE: '.CHtml::dropDownList('lang', '1', language::model()->getLang());?>
<?php echo CHtml::endForm();?>
вот как мне в фреймворковский селект добавить
[ 2. кинул он-ченж к примеру с функцией test ]
ворос в этом был

[guest] Гость
Было сказано: Вторник, 09 Февраль 2010
спасибо за ответы, подсказали на форуме вот такое решение:
<?php echo 'CHOOSE LANGUAGE: '.CHtml::dropDownList('lang', '1', language::model()->getLang(), array ('onChange' => "foo()"));?>может кому пригодится

bambucha
Было сказано: Четверг, 25 Март 2010
А можно использовать спец.символы?
например,
<?php echo CHtml::dropDownList('listname', $select,
array('M' => 'Male', 'F' => '& nbsp;Female'));Результат:
<select id="listname" name="listname">
<option value="M">Male</option>
<option value="F">& nbsp;Female</option>
</select>Т.е. коды спецсимволов не заменяются на соответствующие. Пробел в "& nbsp;" поставлен специально.

[adm] zolter
Было сказано: Четверг, 25 Март 2010
Полез в исходники и все таки нашел. :)
Это можно сделать указав принудительно параметр 'encode' => false
Т.е. вот так:
echo CHtml::dropDownList('listname', $select,
array('M' => 'Male', 'F' => ' Female'), array('encode' => false));

bambucha
Было сказано: Четверг, 25 Март 2010
Спасибо, zolter)
глянул в доках - ничего об этом нет, впредь буду смотреть исходники)

[guest] NickSun
Было сказано: Среда, 28 Апрель 2010
а в чем отличие CHtml::dropDownList() от CHtml::activeDropDownList() ?

[guest] zolter
Было сказано: Среда, 28 Апрель 2010
activeDropDownList - создает выпадающий список для атрибута вашей модели.
а dropDownList - создает обычный выпадающий список.

[guest] NickSun
Было сказано: Среда, 28 Апрель 2010
и еще вопрос по findAll(). че-то у меня при вызове этого метода возвращается массив с кучей всякого ненужного мне хлама, а вот строк из БД нет ни одной. пробовал вызывать с параметрами и без. результат один и тот же. Структура таблицы countries следующая
CREATE TABLE IF NOT EXISTS `countries` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` tinytext,
`shortname` tinytext,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=240 ;создал модель Countries, контроллер CountriesController (хотя как я понимаю он мне в данном случае не нужен, т.к. данные буду только читать из этой таблицы, или нужен?) + еще есть все необходимые вьюхи в которых все отображается как нужно. Да, все это добро генерировал в Gii.
И собственно вопрос: как мне выбрать из таблицы все записи и запихнуть их в выпадающий список? Помогите пожалуйста :)

[adm] zolter
Было сказано: Среда, 28 Апрель 2010
Все достаточно просто. Если модель у нас создана верно, тогда пробуем в любом отображении сделать следующий код:
$a = Countries::model()->findAll();
foreach($a as $key => $val) {
echo $val->name , ",";
}Если на экране увидим название стран через запятую - тогда с получением данных у нас проблем нет, можем создавать выпадающий список:
// при помощи listData создаем массив вида $ключ=>$значение
$list = CHtml::listData($a, 'id', 'name');В $list у нас теперь получился массив всех стран с базы, где ключ - это id, а значение - name. Дальше кидаем это дело в дропдаун:
<?php echo CHtml::dropDownList('countries', $model, $list);Заметь, тут я использую $model а не $a. В данном случае $model это модель твоей формы, для которой ты хочешь выбрать страну. К примеру если ты редактируешь страницу объявления (модель Ads) то переменная $model будет моделью Ads. "countries" в данном случае это название атрибута в моделе $model

[adm] zolter
Было сказано: Среда, 28 Апрель 2010
Кстати, после строчки
$list = CHtml::listData($a, 'id', 'name');можно сделать принтовку и посмотреть какие данные попали в массив:
echo '<pre>';
print_r($list);
echo '</pre>';ну это для того что б понимать какой формат получился, и какие данные в нём есть.

[guest] NickSun
Было сказано: Среда, 28 Апрель 2010
Спасибо! :)
У меня просто было так:
$countries = new Countries;
$countries->findAll();
Ваш код работает, вот только на списке ошибку выдает при попытке сделать следующее:
<?php echo CHtml::activeDropDownList($countries, 'id', CHtml::listData($countries, 'id', 'name'), array('empty'=>"Select country")); ?>

[guest] Гость
Было сказано: Среда, 28 Апрель 2010
первый парраметр где у вас $countries - должна быть модель формы с которой вы работаете.

NickSun
Было сказано: Четверг, 29 Апрель 2010
А что значит модель формы? У меня нет никой модели формы. Можете более раскрыто ответ дать?

[guest] zolter
Было сказано: Четверг, 29 Апрель 2010
Ну смотрите. В начале у вас есть:
CHtml::beginForm($model)
в данном случае $model - это модель которая отвечает за формирование формы. Приеду домой - отвечу более подробно что б было понятно если этого не хватит :)

NickSun
Было сказано: Четверг, 29 Апрель 2010
А у меня такого нет :)
У меня форма начинается с этого:
<?php echo CHtml::form('','post',array('id'=>'homeRegister', 'class'=>'main_register_form')); ?>
<?php echo CHtml::errorSummary(array($user, $user_profile)); ?>
...
<?php echo CHtml::endForm(); ?>

[guest] zolter
Было сказано: Четверг, 29 Апрель 2010
А форма занимается редактированием какой таблицы? т.е. форма что собственно редактирует? страну? юзера? :)

NickSun
Было сказано: Четверг, 29 Апрель 2010
Форма нужна для регистрации юзера. ID страны записывается в таблицу user_profile, а берется списком из таблицы countries

NickSun
Было сказано: Четверг, 29 Апрель 2010
и еще 1 вопрос по поводу форм. как можно вывести ошибки валидации возле полей, а не все сразу (CHtml::errorSummary())?

[guest] zolter
Было сказано: Четверг, 29 Апрель 2010
Форма нужна для регистрации юзера. ID страны записывается в таблицу user_profile, а берется списком из таблицы countries А поля в форме (input-ы) через CHtml сделаны?
Киньте в комменте саму форму

NickSun
Было сказано: Четверг, 29 Апрель 2010
Вот сама форма. Некоторые поля убрал чтоб не засорять эфир :)
<?php echo CHtml::form('','post',array('id'=>'homeRegister', 'class'=>'main_register_form')); ?>
<?php echo CHtml::errorSummary(array($user, $user_profile)); ?>
<?php echo CHtml::activeLabel($user, 'login'); ?>
<?php echo CHtml::activeTextField($user, 'login') ?>
<?php echo CHtml::activeLabel($user_profile, 'countryID'); ?>
<?php echo CHtml::dropDownList('country', $user_profile->getAttributes(array('countryID')), CHtml::listData($countries, 'id', 'name'), array('empty'=>"Select country")); ?>
<?php echo CHtml::endForm(); ?>

[guest] zolter
Было сказано: Четверг, 29 Апрель 2010
Я так понимаю в таблице за которую отвечает модель $user есть поле id_countrie к примеру. Тогда выпадающий список будет выглядеть вот так:
echo CHtml::activeDropDownList($user, 'id_countrie', CHtml::listData($countries, 'id', 'name'), array('empty'=>"Select country"));

[guest] Гость
Было сказано: Четверг, 19 Август 2010
подскажите пожалуйста, в чем моя ошибка. Есть вот такие строки
$mod = tbl_user::model();
$list = CHtml::listData($mod, $a , $b);если просто выводить переменные $a и $b, то они выводятся, но вот массив из них не составляется. при выводе $list показывает просто Array ( [] => )

[guest] Гость
Было сказано: Четверг, 19 Август 2010
всё получилось=)
возник другой вопрос.
$array = CHtml::listData($mod ->findAll(), 'ID', 'lastname');сейчас в список выводиться только фамилия человека, а как сделать, чтобы выводилось несколько полей: фамилия, имя, отчество? пока у меня сделано так:
$executor=mysql_query("SELECT id,name,lastname,patronymic FROM tbl_user");
while ($row = mysql_fetch_array($executor))
{
$fio=$row[2]." ".$row[1]." ".$row[3];
$array[$row[0]]=$fio;
}в этом случае массив готов и listData не нужна.

[guest] zolter
Было сказано: Четверг, 19 Август 2010
А вы после строчки
$array = CHtml::listData($mod ->findAll(), 'ID', 'lastname');сделайте
echo '<pre>';
print_r($array);
echo '</pre>'что б посмотреть в каком формате создает массив listData, и точно в таком же формате делайте свой.

[guest] Гость
Было сказано: Четверг, 19 Август 2010
мой массив создается точно в таком же формате. всё работает как надо. просто мне интересно, можно ли через listData так же сделать или обязательно придется писать стандартный sql запрос и в ручную формировать массив? ведь listData работает только с тем, что есть в форме, а с объединением полей уже ничего не получается.

[guest] zolter
Было сказано: Четверг, 19 Август 2010
Ну как вариант можно перегрузить listData() и научить его склеивать пару полей. Если есть время - это конечно лучший вариант :)

[guest] Гость
Было сказано: Четверг, 19 Август 2010
перегрузить я думаю не вариант, раз быстрого способа нет, оставлю как есть. просто хотелось, чтобы красиво было=) спасибо за ответы.

[guest] Михаил
Было сказано: Вторник, 14 Сентябрь 2010
Ёлы-палы. Уже замучился. Не подскажите, как сделать, чтоб определенный пункт был выбранным.
Т.е. на выходе получить приблизительно такое html:
<select>
<option value="1">Январь</option>
<option value="2" selected>Февраль</option>
<option value="3">Март</option>
......
</select>

[adm] zolter
Было сказано: Вторник, 14 Сентябрь 2010
Да все очень просто, второй параметр - это ключ который будет выбран:
<?php echo CHtml::dropDownList('listname', 2, array(1 => 'Male', 2 => 'Female'));

[guest] Михаил
Было сказано: Вторник, 14 Сентябрь 2010
Спасибо за оперативность, zolter.
Если я Вас правильно понял, то вы предлагаете следующеее (в моем контексте):
echo $form->dropDownList($model, 2, array(
1 => 'Январь',
2 => 'Февраль',
3 => 'Март',
))
Это не работает. Ошибка.Но это и понятно. Возможно я Вас не правильно понял?

[adm] zolter
Было сказано: Вторник, 14 Сентябрь 2010
Просто перед echo $form-> укажите значение для поля по умолчанию. вот так:
$model->pole_name = 2; // значение которое будет выбрано
echo $form->dropDownList($model, 'pole_name', array(
1 => 'Январь',
2 => 'Февраль',
3 => 'Март',
))

[guest] Михаил
Было сказано: Вторник, 14 Сентябрь 2010
Опять же, спасибо за оперативность.
Работает. Только надо в модель добавить свойство pole_name. (В контексте данного примера)
Я начал изучать Yii совсем недавно, возможно туплю.

[guest] Игорь
Было сказано: Пятница, 11 Март 2011
Здравствуйте. А как можно вывести два поля, например
$list = CHtml::listData($models,'category_name category_id', 'category_name category_count'); &

[guest] Саша
Было сказано: Среда, 17 Август 2011
Добрый вечер! Я делаю множественный выбор, пишу 'multiple'=>'multiple', потом в поле записывается в function beforeSave() (в моделе эта функция):
$this->sections=implode(', ',$this->sections);
но потом при открытии формы на редактирование - никаких значений не выбрано///
если только одно значение - то оно выделено , а несколько никак не хотят делаться selected.
подскажите пожалуйста!
использую CHtml::activeListBox или CHtml::activeDropDownList (одинаково не работают как надо)

[guest] maxx
Было сказано: Среда, 17 Август 2011
а распринтуйте данные которые вы передаете в activeDropDownList в качестве параметра для выбора и покажите какие они там.

[guest] Саша
Было сказано: Понедельник, 22 Август 2011
решил проблему - надо обратно преобразовывать в массив и задавать выбранные значения. Добавил в модель ф-цию afterFind() и в ней $this->selection=explode(', ',$this->sections);
затем в форме уже использую не 'sections', a 'selection'
спасибо что помогаете учиться новому ))

[guest] maxx
Было сказано: Понедельник, 22 Август 2011
ага, я на это и намекал что надо бы их обратно к массиву вернуть :) рад что у тебя получилось

[guest] MrArthur
Было сказано: Вторник, 01 Ноябрь 2011
Спасибо большое за статью!!! Никак не мог разобраться, как из бд подгрузить данные в селект...

[guest] JB
Было сказано: Среда, 01 Февраль 2012
Добрый день, подскажите как сделать чтобы один список зависел от другого, то есть при выборе страны в одном списке изменяются доступные города в другом? Спасибо

[guest] zolter
Было сказано: Четверг, 02 Февраль 2012
Я бы рад объяснить, но там на двух пальцах не получится )) Установите себе этот движок (http://yiiframework.ru/forum/viewtopic.php?f=14&t=2548) и посмотрите как реализовал автор.
Там при выборе категории идет автоматическое заполнение селекта с характеристиками для этой категории

[guest] JB
Было сказано: Четверг, 02 Февраль 2012
Да там просто ад)) мне всего 3 значения нужно чтобы выпадало, все равно спасибо)

[guest] Валя
Было сказано: Понедельник, 19 Ноябрь 2012
А что передавать в переменной $select?
<?php echo CHtml::dropDownList('listname', $select,
array('M' => 'Male', 'F' => 'Female'),
array('empty' => '(Select a gender'));$select = array('empty' => '(Select a gender'));или
$select = 'empty';??

[guest] Гость
Было сказано: Суббота, 24 Ноябрь 2012
'M' => 'Male', 'F' => 'Female' передавайте туда ключи массива


