Concatenate strings in CHtml::listData

Hi all, I got the code




    <div class="row">

        <?php echo $form->labelEx($model,'id_manager'); ?>

        <?php echo CHtml::activeDropDownList($model,'id_manager', CHtml::listData(Manager::model()->findAll(), 'id', 'name'), array('empty' => '--- Choose---')); ?>

        <?php echo $form->error($model,'id_manager'); ?>

    </div>



This view displays dropdown list in _form.php (create or save). How can I concatenate strings? I believe this code:

CHtml::listData(Manager::model()->findAll(), ‘id’, ‘name’

displays values on the list, but I would like to concatenate surname column to this, when I do:

CHtml::listData(Manager::model()->findAll(), ‘id’, ‘name’.’ surname’

I get error:

[color="#FF0000"][b]CException

Description

Property "Manager.namesurname" is not defined.[/b][/color]

What should I do to display concatenated strings on this dropdown?

Is there possibility to concatenate 2 text columns directly in the view? Or can I only write function in model to get fullname and then execute thin funtion in view (thanks Antonio…).

Any suggestions?

Thanks

Tom

p.s: not tested

model/Manager.php




	public function getConcatened()

	{

		return $this->name.' '.$this->surname;

	}






	public function getManagers()

	{

		$criteria=new CDbCriteria;

                ...


		$models = Manager::model()->findAll($criteria);

 

		$list = CHtml::listData($models, 'id', 'concatened');

		

		return $list;

	}






echo CHtml::activeDropDownList($model,'id_manager','concatened'));



Yeah it works in that way, 1) define function in model to concat name and surname, 2) call this function in view, but I was hoping that I can concat name and surname somehow just there in view - it seems to be so simple task.

Unfortunately there is no other way. CHtml::listData() is not that smart to understand strings like “name surname” :) Usually I generate such data for dropdowns manually.

Well I believe that one of the arguments passed to the CHtml::listData() is (beside models and ids) string $textField (database column/model property) which will be displayed on dropdown for corresponding id value. Concat is one of the simplest operations :rolleyes: so maybe yii 2.0 will have this feature. On the other hand being unable to concat this in view, pushed me to be follow MVC and don’t put any logic (as concat) in view :rolleyes:

You can’t pass ‘name’.’ surname’ to listData method, because it will try to find namesurname model’s property. You can try to extend this method so that it will take an array of strings and a separator, or a string like “@name @surname” and then parse it…

Well now I know difference between passing and rendering. So you mean I can try to extend CHtml::listData() function in yii framework source files, so it accepts more than property (for example concatenation of properties…)?

I mean extend CHtml class by adding your own method “listDataEx” and put the class into protected/components directory. listDataEx() should accept an array of attributes’ names as a 3rd parameter. Let’s look at the listData() code, it contants following strings:




$text=self::value($model,$textField);

$listData[$value]=$text;



You’ll need to replace the 1st string with something like:




foreach ($textField as $attr)

    $text.=self::value($model,$attr).' ';



Hope you got the idea :)

This is exactly as writing a property named this way:

public function getNameSurname(){

return $this->name . ’ ’ . $this->surname;

}

That will work.


andy_s’s right and there is NO WAY JOSE that Yii could even imagine that the value passed is actually two column names concatenated… How does it know? Is there any parameters or settings that says to look at that?

Could be cool but if there is no way to tell the object that two concatenated columns are passed by, then the assumption to guess that the object will ‘intelligently know’ that there are in fact two columns is wrong.


Maybe it is a cool feature, you are right but that should be in the way of:

CHtml::listData(Manager::model()->findAll(), array(‘id’, array(‘name’,‘surname’));

Where array is a list of column names that if column name is array, then it should concatenate the column names within in the current position…

mmm… I think we’ve got a winner… what do you think?

Could be nice to pass a separator too (’ ’ in our case). But anyway, this method won’t be universal, because one day some one will want to add some text to each dropdownlist row or to number them :))

I realize this is an old thread but wanted to solicit some feedback on an approach:


echo $form->dropDownList($model, 'creator_id', 

	CHtml::listData(account::model()->findAllbySql(

		'SELECT account_id, CONCAT(first_name, " ", last_name) as last_name FROM account'

		), 'account_id', 'last_name'),

	array('prompt'=>'Choose...')

);

If the fullname is only being used for display purposes here, is there any problem to doing it this way? Seems to work.

Neat solution, but it’s always better to put that in the Model, IMO.

What will you do if/when the db schema changes? :)

check this

stackoverflow[dot]com/questions/12812062/in-yii-framework-how-can-i-combine-two-columns-and-show-as-display-string-in-dro

or

stackoverflow[dot]com/q/12812062/1343222

it contains a nice solution

For those still looking for a solution for this, it’s rather simple (I keep getting this post as one of the first replies in google so adding this solution hopefully helps some people)

in the model you’re using to fill the listData, add the following code




	public function __get($key){

		$action = 'get'.str_replace(' ','',ucwords(str_replace('_',' ',$key)));

		if(method_exists($this, $action)) return $this->$action();

		return parent::__get($key);

	}

	public function getFullName(){

		return $this->name.' '.$this->first_name;

	}



its a magic function that allows you to call a method as an attribute

so you can build your listData like this:




CHtml::dropDownList('listPeople', $model->person_id, CHtml::listData($people, 'person_id', 'full_name'));



Antonio - I like the way you think !

I need to put an array of url’s in a listBox. I think this might be what I need.

Try this

<div class="row">

    &lt;?php echo &#036;form-&gt;labelEx(&#036;model,'id_manager'); ?&gt;


    &lt;?php echo CHtml::activeDropDownList(&#036;model,'id_manager', CHtml::listData(Manager::model()-&gt;findAll(), 'id', 'concate'), array('empty' =&gt; '--- Choose---')); ?&gt;


    &lt;?php echo &#036;form-&gt;error(&#036;model,'id_manager'); ?&gt;


&lt;/div&gt;

create getconcate method in model and call in form

public function getConcate()


{


    return &#036;this-&gt;name.&quot;-&quot;.&#036;this-&gt;surname;





}

Custom Data Attributes

Does anyone knows how to add Custom Data Attributes (HTML5 data-*) to dropDownList

Country table (id, name, iso_code, calling_code)


<select name="Country[id]" id="Country_id">

<option value="">Select Country</option>

<option value="1" data-ISO="USA">United States (+1)</option>

<option value="1" data-ISO="GB">United Kingdom (+44)</option>

</select>


echo $form->dropDownList(Country::model(), 'id', 

CHtml::listData(Country::model()->findAll(), 'id','fullName'),

array('prompt' => 'Select Country', 

); 

 

function getFullName()

{

return $this->country_short_name.' (+'.$this->calling_code.')';

}

In htmlOptions you can add "options" that will do exactly what you want.


'options' => array(

  'value_of_option_1' => array('data-ISO' => 'USA'),

  'value_of_option_2' => array('data-ISO' => 'GB')

)

Replace value_of_option_x with your actual values (your example has "1" for every option which is not correct I presume.)