Using the sorting and pagination in ClistView we have urls like:
controller/action?Model_page=NUM&Model_sort=COL.
Is it possible to make urls look like
controller/action?page=NUM&sort=COL.
and if it is possible, how can i make it?
Yes, you can set these parameters when you create your CActiveDataProvider:
$myDataProvider = new CActiveDataProvider('MyModel', array(
'sort'=>array(
'defaultOrder'=>'id DESC',
'sortVar'=>'sort' // set the sort parameter
),
'pagination'=>array(
'pageSize'=>5,
'pageVar'=>'page' // and and page param here
),
));
Related
hello i am creating a search module which is taking data from apis..
Now i am getting all result in 1 api call and i am making it as a dataProvider.
this is the code..
$dataProvider = new CArrayDataProvider($result, array(
'sort' => array(
'attributes' => array('name',
),
),
'pagination' => array(
'pageSize' => 10,
),
));
this is working fine and giving pagination. What i want to do is to use limit and ofset of api.
for eg consider the yelp api
http://api.yelp.com/search?term="xxx"&location="xxx"&limit=10&ofset=0;
i want to get only 10 result initially and i need another api call to get next set when i click the pagination [2] or next >.
how can this be done ?
I also need a expert opinion. which one is better.? calling api at single time and fetch all detail once or getting few one by one ? the expected results will be around 200..
Yelp doesn't allow to "cache" its search results in any meaning http://www.yelp.com/developers/getting_started/api_terms (section 6). So I believe you need to do call each time pagination link is clicked.
For this purpose I would create some YelpDataProvider extended from CDataProvider and override required abstract methods.
Pagination:
Not sure I got what kind of problem you faced with, but if you implement your own data provider you will have access to CPagination class instance and its properties pageSize and offset.
pageSize is to be mapped to limit yelp request parameter, offset property - directly to offset request param.
I hope this will help.
http://www.yiiframework.com/doc/api/1.1/CPagination
$dataProvider = new CArrayDataProvider($result, array(
'sort' => array(
'attributes' => array('name'),
),
'pagination' => array(
'pageSize' => 10,
'offset' => 5
),
));
I'm new to Yii, and I'm having a hard time figuring this out. I want to show multiple CGridViews on a page depending on the options that a user chooses, with each gridview only showing the records for that option. In this case, the options are job statuses, like open, closed, in progress, etc.
I've got some code working to show multiple grid views by looping through an array, but I'm not sure how to filter them:
$test = array(1,2,3,4,5);
foreach ($test as $value) {
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid',
'dataProvider'=>$model->search(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
/* etc */
),
));
}
Any ideas about how I can go about filtering each gridview from the values in the array?
Thanks!
UPDATE
Ok, I figured out how to do what I was trying to do. I'm handling it in the controller like this:
public function actionBoard()
{
$models = array();
$statuses = JobStatus::model()->findAll();
foreach ($statuses as $status)
{
$model=new Job('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Job']))
$model->attributes=$_GET['Job'];
$model->Status = $status->ID;
$models[$status->Status] = $model;
}
$this->render('board',array('models'=>$models));
}
So I find all the statuses, then use the ID field to do a search, put the result in an array, then pass it to the view. I handle it like this in the view:
foreach ($models as $status)
{
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid',
'dataProvider'=>$status->search(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
'Phone1',
'Phone2',
/* etc */
),
));
Basically, creating a gridview for each "status" in the array of "statuses". Seems to work, just took some time to think of it in MVC terms instead of the old ASP.NET databinding method that I'm used to.
You asked for different CGridViews, so here it is:
Go in your model.
Now, you need to write some new search() methods.
Within each method, you will specify the values that you want, like these 2 methods:
public function searchA() {
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('email', $this->email, true);
$criteria->compare('password', $this->password);
$criteria->compare('created', $this->created);
$criteria->compare('lastmodified', $this->lastmodified);
$criteria->compare('confirmed', $this->confirmed);
$criteria->compare('is_human', 1);// this is a human
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
public function searchB() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('email', $this->email, true);
$criteria->compare('password', $this->password);
$criteria->compare('created', $this->created);
$criteria->compare('lastmodified', $this->lastmodified);
$criteria->compare('confirmed', $this->confirmed);
$criteria->compare('is_human', 0);//this is not a human, maybe a donkey ... who knows
$criteria->compare('username', $this->username, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
now that you have your search methods, use the needed search method for each cgridview
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid',
'dataProvider'=>$model->searchA(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
/* etc */
),
));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid2',
'dataProvider'=>$model->searchB(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
/* etc */
),
));
simple
ps: as a trick, you may want to use constants, like:
const CONSTA = 1;
const CONSTB = 2;
and use then in the model as:
self::CONSTA
or outside the model as:
ModelName::CONSTA
by using const, if your values change in time, you dont have to modify the entire code and you dont have to look all over the project for those values
You should begin at the data part of the problem: First try to create several data providers that return the results that you want. If you used Gii to auto-generate some models, you can look into the search() method there to see an example how you can create such a provider with different query conditions. You should try to keep this code in a model somewhere. For example you could create a searchByStatus($status) method, which returns a data provider for the given status.
Then in the controller you can fetch several data providers from this method, one for each status you want, send them to the view and finally feed them into different CGridViews.
Here is a wiki for dynamic gridviews in the same view.
here i am using the ajax request to delete the record from the clistview the record is deleting succesfully but the list view is not updating if we refresh the page then only the record is removing from the clist view can any one help here is my code
<?php
echo CHtml::link(CHtml::encode('Delete'), $this->createUrl('delete', array('id' => $data['id'])), array(// for htmlOptions
'onclick' => ' {' . CHtml::ajax(array(
'type'=>'POST',
'beforeSend' => 'js:function(){if(confirm("Are you sure you want to delete?"))return true;else return false;}',
'url'=>$this->createUrl('delete', array('id' => $data['id'],'ajax'=>'delete')),
'complete'=>'js:function(jqXHR, textStatus){$.fn.yiiListView.update("firstlist");}'
)) .
'return false;}', // returning false prevents the default navigation to another url on a new page
)
);
here is the code for clistview
<?php $this->widget('zii.widgets.CListView', array(
'id' => 'firstlist',
'dataProvider'=>$dataProvider,
'itemView'=>'_beneview',
'enablePagination' => false,
'summaryText' => '',
)); ?>
You could use CHtml::ajaxLink for ajax request, but your way is also fine.
I have filtered CListView results also with paginations enabled, you can just look at the major things for updating list view on this link
Please check view part and updating script part.
Hope his will help.
Use CGridView, you can add CButtonColumn
I have problems regarding with pagination and Ajax form.
Here is my code for Controller:
$dataProvider = new CActiveDataProvider('User', array(
'pagination'=>array(
'pageSize'=>10,
),
));
$this->render('users',array(
'dataProvider'=>$dataProvider,
));
For view -> users:
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_user',
);
For render _users:
echo CHtml::ajaxLink($text, $this->createUrl('admin/deleteuser',array('id'=>$data->iduser)), array('success'=>"js:function(html){ alert('remove') }"), array('confirm'=>_t('Are you sure you want to delete this user?'), 'class'=>'delete-icon','id'=>'x'.$viewid));
if i have 15 rows in a database it will only show 10 and will generate a pagination (ajaxUpdate = true) for next 5. The first 10 rows has no problem with the ajaxLink because the clientscript was generated but problem is the when I move to the next page, the ajaxLink is not working because its not generated by the pagination .
any idea? thanks
An alternate method, check this post in the yii forum. So your code will become like this:
echo CHtml::link($text,
$this->createUrl('admin/deleteuser',array('id'=>$data->iduser)),
array(// for htmlOptions
'onclick'=>' {'.CHtml::ajax( array(
'beforeSend'=>'js:function(){if(confirm("Are you sure you want to delete?"))return true;else return false;}',
'success'=>"js:function(html){ alert('removed'); }")).
'return false;}',// returning false prevents the default navigation to another url on a new page
'class'=>'delete-icon',
'id'=>'x'.$viewid)
);
Your confirm is moved to jquery's ajax function's beforeSend callback. If we return false from beforeSend, the ajax call doesn't occur.
Another suggestion, you should use post variables instead of get, and also if you can, move the ajax call to a function in the index view, and just include calls to the function from the all links' onclick event.
Hope this helps.
Not fully sure, but given past experiences I think the problem is in the listview widget itself.
If the owner of the widget is a Controller, it uses renderPartial to render the item view.
Renderpartial has, as you may or may not know, a "processOutput" parameter which needs to be set to TRUE for most of the AJAX magic (its FALSE by default).
So perhaps you can try to just derive a class of the listview and add a copy in there of "renderItems()". There you would have to change it so that it calls renderPartial with the correct parameters.
In the widget Clistview, I added afterAjaxUpdate
$jsfunction = <<< EOS
js:function(){
$('.delete-icon').live('click',function(){
if(confirm('Are you sure you want to delete?'))
{
deleteUrl = $(this).attr('data-href');
jQuery.ajax({'success':function(html){ },'url':deleteUrl,'cache':false});
return false;
}
else
return false;
});
}
EOS;
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'id'=>'subscriptionDiv',
'itemView'=>'_subscription',
'afterAjaxUpdate'=>$jsfunction,
'viewData'=>array('is_user'=>$is_user,'all'=>$all),
'htmlOptions'=>($dataProvider->getData()) ? array('class'=>'table') : array('class'=>'table center'),
)
);
and in the _user just added attribute data-href
<?php echo CHtml::ajaxLink($text, $this->createUrl('admin/deletesubscription',array('id'=>$data->idsubscription)),
array('success'=>"js:function(html){ $('#tr{$viewid}').remove(); }"),
array('confirm'=>_t('Are you sure you want to unsubscribe?'),
'class'=>'delete-icon',
'id'=>'x'.$viewid,
'data-href'=>$this->createUrl('admin/deletesubscription',array('id'=>$data->idsubscription))
)); ?>
try
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_user',
'enablePagination' => true,
);
if this doesn't solve, try including the total number of records in the data provider options as -
'itemCount' => .....,
I had created with custom field in yii Cgridview but how to make that sortable. The custom field value is from a function in the model. I want to make this field sortable?
Can someone help me?
In the search function of your model, where customField is the name of your field:
// ...other criteria...
$criteria->compare('customField',$this->customField);
$sort = new CSort();
$sort->attributes = array(
'customField'=>array(
'asc'=>'customField ASC',
'desc'=>'customField DESC',
),
'*', // this adds all of the other columns as sortable
);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort,
));
You may also need to update rules and attributeLabels in your model to reflect the new custom field.
There is a detailed description about searching on custom fields at this URL:
Using standard filters in CGridView custom fields