Yii Paging

How would I paginate something like this…

Here’a my view




<?php $this->renderPartial('_cats',array(

            'category'=>$model,	

          

			'products'=>$model->products,			

        )); ?>

and my _cats page


<?php foreach($products as $product): ?>

		

	

		 <?php echo CHtml::link("{$product->Name}",array('/products/view', 'id'=>$product->ID)); ?>

			

	<?php echo CHtml::image(Yii::app()->baseUrl . '/images/uploaded/' . $product->Image, 'alt',array('width'=>237,'height'=>159)); ?>

	

	

	

		

			

 

        <?php endforeach; ?>

		

				



Inside Controller


public function actionView($id)

	{

		$this->render('view',array(

			'model'=>$this->loadModel($id),

		));

	}

Sometimes I can get around 30 results with images and it would be nice if I can for instance put 10 items on each page. Couldn’t find anything on pagination unless ClistView or dataProvider is being used and I’m not using either.

EDIT: just saw you weren’t using clistview. sorry

Are you tying to achieve something like this(i have this page set to 10 and my other set to 30)?

3467

Untitled-3.jpg

(partial screen shot of my project)

If so it’s just clistview with css. Ill post the code if it is what your trying to accomplish. Let me know.

I’m not using ClistView that’s the issue, what I want is just split my content into pages. So 10 products on page 1, the next 10 on page 2 and so on. It’s straight forward when using dataprovider and ClistView. In my situation though I’m using a loop to get my products and my own view.

EDIT. I would like to see your code either way if you don’t mind.

As requested!

I am using yii-attachment-behavior for image uploads. You can see all the comments I put in the comments of the extension if you want to use this. I’m not going to post the model portion for the attachement-behavior you can go to the ext. to see it.

views/products/index.php


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

        'dataProvider'=>$model->search(),

        'itemView'=>'productgallery',

        'template'=>'{pager}{items}<br/>{pager}',       

        'sortableAttributes'=>array(

	    'model', //don't get this confused this is my 'name' column

	    'company_id',

        ),

)); ?>

views/products/productgallery.php




<div class="productimg">

    <?php echo CHtml::link('<img src="../'.$data->getAttachment('thumb').'" />', array('view', 'id'=>$data->product_id)); ?><br>

    <div class="productimgdesc">

        <h5>

        <?php echo CHtml::link(CHtml::encode($data->company->name),array("companies/view","id"=>$data->company_id)); ?> <br>

        <?php echo CHtml::link(CHtml::encode($data->model),array("products/view","id"=>$data->product_id)); ?>

        </h5>

    </div>

</div>




EDIT: I changed this becuase I didn't have a set way to ensure the products

image size would render the size i wanted them to every time to make sure my 

pretty css didn't get jacked up + it's on auto (see the css).  It will not keep 

proportions but it will show them in a set size. I didn't want to relie on someone's server to have the proper image stuff installed. 

The alt portion is just in case it can't find the image or default image it

it shows those words so I know where to look for the problem and it doesn't 

leave the screen blank.


<div class="productimg">

    <?php

    $imagelink = '<img src="../'.$data->Attachment.'" style="width:270px;height:135px;" alt="Can\'t Find Product Image Directory" />';

    echo CHtml::link($imagelink, array('view', 'id'=>$data->product_id)); ?><br>

    <div class="productimgdesc">

        <h5>

        <?php echo CHtml::link(CHtml::encode($data->name),array("products/view","id"=>$data->product_id)); ?> <br/>

        </h5>

    </div>

</div>






models/products.php


public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;

		...

		return new CActiveDataProvider($this, array(

			 'pagination'=>array(

				'pageSize'=>'10', //could put 1, 2, 3, 10, 20, 30, etc. however many you want to display per page. 

                                ),

				'criteria'=>$criteria,

				));

	}

I’m letting the user select 10, 20, 30, 50 per page so my code if different but in your case if you only want 10 per page it is default so you can leave the portion above default gii. Or I believe that is how you make it preset value.

my theme/css/yourname.css


div.productimg

  {

  border:2px solid #f7f7f7;

  height:auto;

  width:auto;

  float:left;

  text-align:center;

  margin:4px;

  opacity:1.0;

  }

div.productimg img

  {

  display:inline;

  margin:3px;

  border:10px solid #ffffff;

  }


div.productimgdesc

  {

  text-align:center;

  font-weight:normal;

  border-top:2px solid #f7f7f7;

  width:100%;

  }

  

img:hover

{

opacity:.7;

filter:alpha(opacity=70); /* For IE8 and earlier */

}



Then of course you have to register the css in your theme/layouts/main.php

NOTE: My header and footer are in different files than the main.php so mine gets registered like this. Register yours how the other css are being registered at the top of your main.php. Or just add it to an existing css at the bottom.


<?php

	  $cs->registerCssFile($baseUrl.'/css/yourname.css');

protected/controllers/productscontroller.php

No edits

Maybe that will help your or maybe someone else good luck!

@ItsYii: ClistView is definitively the best way to handle your request.

@skworden: good example

Thanks, I think it is too. That’s why I’m using it :)

@skworden I appreciate your help and I would like to say thanks. Your example was very well put.

My situation is slightly different and using ClistView is slightly more complicated for me. I didn’t post what I wanted to do fully because of over complicating a question. First of all the page I will view has products displaying on the category view.php.

I’m also joining tables in the process which makes things more complex.

Either way I realized if I want to page with Yii I can only use dataProvider/ ClistView or so I assume.

This is what I have done so far on my controller, the view is not important right now.




public function actionView($id)

	{

	 $criteria = new CDbCriteria();


	

	 $cat = ECCategory::model()->findAll();

	 

	 foreach($cat as $cats){

	 


	 

	 if($cats->ParentID == $id){

	 $criteria->condition='t.ParentID='.$id; // that is if there are more category inside category show them

				

				}else{ // else display the products belonging to that category

				$criteria->join='RIGHT JOIN ECProduct AS b ON t.ID = b.CategoryID'; 

				

				$criteria->condition='t.ID='.$id;

				

				}

				

				


	 }

	 

	 

	 

	

	

	$dataProvider=new CActiveDataProvider('ECCategory', array(

    'criteria'=> $criteria

		));

		

	

		$this->render('view',array(

			'model'=>$this->loadModel($id), 'dataProvider'=>$dataProvider,

		));

	}

// my if doesn’t work, basically what I want to display is two different views for 2 different conditions. However it can only satisfy one condition, currently the if will ignore the 1st part and jump to else. Should I comment the else it will satisfy the 1st. If I can get and alternative or a way to make my IF condition work then that will be all.

Thanks for reading

Cheers

In plain terms:

It appears you are tying to have a page that shows all your products. You can then filter down the products based on a category…Is this correct?

If so right now I’m working on something similar however a little bit more complex.

In short I have Products each product belongs to a category.

Each category can have a parent category and has to be added dynamically from the admin panel and will show up on the products page.

Thus, the product can belong to many categories.

Each product has many features… i.e. bluetooth, wifi, etc that are also added dynamically and added to the products page. Each product can have many features.

Then on the products page you can filter down based on category, manufacturer (brand), and features via ajax tree/check boxes. If this is similar to what you are doing let me know. It’s kinda like on ebay or amazon when your looking for products. This will take me a day or two to complete because I have to figure out the best way to do it. I have one method but I don’t like it because it’s wayyyy to complicated and I like simple code that uses almost all default Yii as you can tell by my previous post.

Yes that’s where I’m heading. I decided to not paginate my category because I never have too many categories in one category (9 is the max). So this way I mixed it up a bit.

I got my Controller, because of my condition this will only display products belonging to a category and never a category belonging to a category.


public function actionView($id)

	{

	 $criteria = new CDbCriteria();


	 $cat = ECCategory::model()->findAll();

	

	$criteria->join='JOIN ECCategory AS b ON t.CategoryID = b.ID';

	$criteria->condition='b.ID='.$id;

    $criteria->select=array('"t".*',

		'"b"."Name" AS "cName"',

	'"b"."ID" AS "cID"',

		 

	 );

	

	$dataProvider=new CActiveDataProvider('ECProduct', array(

    'criteria'=> $criteria,

	 'pagination'=>array(

      'pageSize'=>9,

    ),

		));

		

		$this->render('view',array(

			'model'=>$this->loadModel($id), 'dataProvider'=>$dataProvider,

		));

	}

This is my view


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

    'dataProvider' =>$dataProvider,

	'itemView'=> '_prods',  // This is for the Products, 

	'summaryText'=>'',

	'emptyText'=>'',

));

	 

	 ?>

<?php $this->renderPartial('_cats',array(       // This render partial is for the category,

            'category'=>$model,	    

           'category'=>$model->category,        

		//	'products'=>$model->products,			

        )); ?>






That’s the best I can do and it works, I’m probably going to do the same for the Admin section (join the tables and make one admin section).

So far on Admin I can go through Categories via JS like so




Yii::app()->clientScript->registerScript('search ', "








$('.search-button').click(function(){

	$('.search-form').toggle();

	return false;

});

$('.search-form form').submit(function(){

	$.fn.yiiGridView.update('eccategory-grid', {

		data: $(this).serialize()

	});

	return false;

});


$(document).on('click', 'td.myLink a', function(){


 var tr = $(this).parent().parent();

 

    $('input[name=\"ECCategory[ParentID]\"]').val($(tr.find('#mainID')).html());

        

        $('.search-form form').submit();

});


");



So everytime I click a categroy it takes me to it’s child categories. I’m going to need to make the ParentId=0 display before anything, create a JS back button and join the Products table. I posted this because it might be of use to you since we are almost doing identical things

Let me know how you get on with yours please.

Cheers

Thanks for posting that, I will look at it some more tomorrow. I’m going for this look (just make a simple Photoshop image. I’m going to attempt to get this working tomorrow as well.) to filter my products. Here is what I’m going for (left side of the picture i put in my first post).

3476

Untitled-3.jpg

I want to filter products via ajax from a category tree. You can add manufacturers, categories and features via admin. You assign the products to categories/features when creating/updating them using tabular input and ajax. That’s the plan. I’ll let you know when I get it to work.

That sounds good, one major issue I faced was the drop down menu. Not sure if you will use that to on your Forms for creating products. I though it will be good if users could dynamically change the category they want to place their products in via drop downs. Just couldn’t get all products and category in a tree like structure on the drop down list. I gave up on it at the end.

Looking forward to seeing what you will do

I ended up driving home today (6hr) from a business trip so I was unable to work on this today. I was thinking of using some sort of check boxes to assign it to categories or maybe a drop down. I will play with some other scripts I have (one does checkboxes and the other does dropdown) and see what I think is more user friendly and makes the most sense to me.