ActiveDropDownList - Please select


(Florian Fackler) #1

Hi,

Don’t know if it’s an idea for a new feature, or if I only didn’t find it in the documentation. I have 2 models in relation eg. User and Country. So in the rules of User-model i have “allowEmpty=>true”. This means, the user CAN specify his country.

This is where my nightmare starts.

When creating an activeDropDownList like:




<?php

$options = CHtml::listData(Country::model()->findAll(), 'id', 'name');

echo CHtml::activeDropDownList($model,'country_id', $options);

?>



the user has no possibility to leave this one out, because the first entry is always selected.

Then I had the Idea to prepend an empty array_element “array(’’=>‘Please select your country’)” like this:




<?php

$select = array(''=>'Please select your country');

$options = CHtml::listData(Country::model()->findAll(), 'id', 'name');

echo CHtml::activeDropDownList($model,'country_id', array_merge($select, $options));

?>



This time everything looks good … but isn’t! Array_merge() throws away all array_keys (array_merge_recursive too). So all my IDs for the countries all get lost and first entry in the DropDown gets ID 0, second ID 1 and so on.

Then I had the idea to convert the ID to a string to prevent php from rewriting the keys:




<?php

// Country.php - The country model

[...]

    public function getStringId()

    {

        return (string) $this->id;

    }

?>



then justify the dropdown:




<?php

$select = array(''=>'Please select your country');

$options = CHtml::listData(Country::model()->findAll(), 'stringId', 'name');

echo CHtml::activeDropDownList($model,'country_id', array_merge($select, $options));

?>



… and guess what - this doesn’t work either :( … only by prepending a char PHP doesn’t throw away my keys:




<?php

// Country.php - The country model

[...]

    public function getStringId()

    {

        return (string) 'X'.$this->id;

    }

?>



… but this time the populated data doesn’t work and I also think there has to be a more gentle way to solve this. Am I right?

My idea for a feature would be to get this possibility to prepend a "Choose your …" for dropdowns if empty values are allowed.

But never the less, I need a quicker solution than waiting for 1.2 ;)

Does anybody could help me out of this?

Thank you!


(Ujovlado) #2

i think you are too lazy to read documentation :P

you have two tables, Countries and Users

Countries has: country_id, country_name

User has: user_id, user_name, country_id

and here you can select a country when editing user information




echo CHtml::activeLabelEx($model,'country_id');

echo CHtml::activeDropDownList($model,'country_id', CHtml::listData(Countries::model()->findAll(), 'country_id', 'country_name'));



or if you select all countries and have an array of them

for example;




$countries = array(6 => 'Slovakia', 12 => 'Poland', 25 => 'United States');



you can add a "zero" country:




$countries[0] = "---";



and the view:




echo CHtml::activeLabelEx($model,'country_id');

echo CHtml::activeDropDownList($model,'country_id', $countries);



this is it:

http://www.yiiframework.com/doc/api/1.0.11/CHtml#activeDropDownList-detail

;)


(Qiang Xue) #3

Please read http://www.yiiframework.com/doc/api/1.0.11/CHtml#activeDropDownList-detail

You can set ‘empty’ or ‘prompt’ option in $htmlOptions


(Ujovlado) #4

yes, you’re right :) and in activeListBoX too, becaues it’s a special type of activeDropDownList.

but i want to show him another way too.

;)


(Florian Fackler) #5

Thank you funner,

You won’t belive how much I’m reading all day/night long about yii, which fascinates me a lot. First time that I get first real life results within a few weeks. (OK, except of cake, which is too heavy and overloaded in my opinion).

Your way was not exactly the solution, because

[list=1]

[*]the country id 0 is appended to the end of the list (I know there are ways to get it up) and

[*]when trying to save country id 0 I get an exception from the DB that no foreign key could be found, so for this special case I’d need to write an beforeSave() “if field==country_id and id=0 then country=null”-function to set country id 0 to NULL.[/list]

But … your answer pointed me into the right direction and now I have what I was looking for:

The htmlOption "empty". Just in case someone else is blind too - just like me:




<?php

$countries=CHtml::listData(Country::model()->findAll(), 'id', 'name');

echo CHtml::activeDropDownList($model,'type_id',$countries,array('empty'=>'Please select a country'));

?>



Thank you and happy coding

Florian


(Florian Fackler) #6

oh … waited too long with my post (had a phone call) :)

Thank you again!


(Ujovlado) #7

there’s no need to write beforeSave() method … only if you have (and you have) an innodb table with foreign keys.

if you set the country_id in Users to integer e.g. [sql]INT(10)[/sql], set [sql]DEFAULT NULL[/sql] and enable [sql]NULL[/sql]everything will be ok :)

and what about the "zero" country at the end?

use asort() function in PHP:




asort($countries);




(Fixticks) #8

i used this coz sometimes it would not select the ‘Please Select’ option as default.


echo CHtml::dropdownlist('countries','',CHtml::listData($countries,'id','name'), array('empty'=>array('0' => '--- Please Select ---')));