CListView and additional columns

Hello fellow programmers.

This is my first post here.

I want to ask how can I change the layout of the standard CListView so it displays items in two columns.

The CSS solution with float is not the case here because I want to have irregular item height and with CSS float each item’s top line is kinda vertically aligned with the adjoined item’s top line.

Is there any solution better than just modyfying actual widget code?

Sorry for eventually bad english, it’s not my national language.

( Any tips according to english syntax would be awesome :slight_smile: )

Kind regards,

Amon

How would you modifiy the widget code?

Note that CListView uses a view file to render the items set with itemView so you just need to write a proper view file and CSS for it…

You have to first make the page structure as a normal (X)HTML page… and then put that inside the view file and the CSS for it…

BTW: welcome to the forum…

Well, just by editing the renderItems() method from CListView.php file in zii/widgets.

Or by making a new class derived from CListView.

Yes, I know that, but you see, CListView renders items in a single column ( by default it is "div" container with "items" class ) and what I want to achieve is to make it render half of the items encapsulated in another div.

Well, that’s pretty obvious :slight_smile:

I’m not a newbie webmaster, just new to Yii framework :slight_smile:

Thanks.

Check again the CListView code… it does not output any HTML code by itself… all the code is in the view file…

so for your need IMO you don’t need to extend it … you just need to make a proper view file…

The div you are talking about is in the _view.php file created by default with Gii…

It does not? So what these statements do in the renderItems() method in CListView class:


	public function renderItems()

	{

		echo CHtml::openTag($this->itemsTagName,array('class'=>$this->itemsCssClass))."\n";

		...

		echo CHtml::closeTag($this->itemsTagName);

	}

This is the behaviour I wanted to change. The above code by default encapsulates all separate items ( which view file is the _view.php file you mentioned ) with a {itemsTagName} with {itemsCssClass}.

By modifying _view.php file ( name of the file can be changed through itemView property ) we are changing the view of the item, not the whole list.

For example if I had a list consisting of 6 elements, and put "<div class="test"></div>" in that file, I would get:




<div class="items">

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

</div>



And what I want to achieve is for that example:




<div class="somecustomclass">

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

</div>

<div class="somecustomclass">

<div class="test"></div>

<div class="test"></div>

<div class="test"></div>

</div>



I’m pointing out that this is one portion of data from CActiveDataProvider so declaring two widgets in the action view file does not come into play.

I see I’m a terrible speaker but you should know from now what I had in my mind.

I understood what you need now…

The CListView as is implemented now does output all items inside one container… "itemsTagName"… but you want to have more containers…

One solution would be to leave the main container… then in the view you can output the "row" container and the items…

you only need a way to count the number of items inside the row containers (3 as per your example)… for that you can use some static variable…

Thanks, and this is my solution to share:

It encapsulates half of items in another container after the middle element.

When declaring the widget just pass the data provider’s itemCount to the viewData property.




<?php $this->widget('zii.widgets.CListView', array(

	'dataProvider'=>$dataProvider,

	'itemView'=>'_view',

	'viewData' => array(

		'itemCount' => $dataProvider->getItemCount(),

	),

));

Then in the beginning of item’s view file use it like that:




<?php

if($index==$itemCount/2 || $index==$itemCount-1) { ?>

</div>

<?php }

if($index==0  || $index==$itemCount/2) 

{ ?>

<div class="itemsColumn">

<?php } ?>

The $index variable is by default available in the item view file and contains the numerical index of the current rendered item ( I mean it counts the elements on each page from the beginning ) so the code is correct for every page.

Any reason why to send the $dataProvider->getItemCount() separately… as you are already sending the $dataProvider… in the view you can have something like


$itemCount=$dataProvider->getIdemCount();

The $dataProvider is not visible to item view file.

But you can use $widget->dataProvider instead.

So now full solution is to put in the beginning of item view file the following code:




<?php

$itemCount=$widget->dataProvider->getItemCount();

if($index==$itemCount/2) { ?>

</div>

<?php }

if($index==0  || $index==$itemCount/2) 

{ ?>

<div class="itemsColumn">

<?php } ?>

And on the end:




<?php if($index==$itemCount-1): ?>

</div>

<?php endif; ?>



No extra widget configuration needed.

Good one… that’s the beauty of Yii… simple and effective…

@mdomba, I think you had forgotten the more important which Yii is beauty… the Yii Community