I am using ArrayDataProvider and i want to know how to make the sort links in view like a
$sort->link('date')
in yii/data/Sort
Follow this (yii\data\sort) and this (yii\data\ArrayDataProvider) documentation
what you can do is make sort like this:
$sort = new Sort([
'attributes' => [
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
'default' => SORT_DESC,
'label' => 'Name',
],
// or any other attribute
],
]);
after that you can put it in your array data provider
$query = new Query;
$provider = new ArrayDataProvider([
'allModels' => $query->from('post')->all(),
'sort' => $sort, // HERE is your $sort
'pagination' => [
'pageSize' => 10,
],
]);
// get the posts in the current page
$posts = $provider->getModels();
and finally in your view:
// any attribute you defined in your sort defination
echo $sort->link('name') . ' | ' . $sort->link('age');
Related
I am getting my dataProvider from which I try to remove some models that don't meet the wanted criteria. This filter is not SQL related and therefore I can't apply it directly to the query. On my view the pagination links are displayed if I leave the dataprovider just as it was. But after I apply the filters to remove the unwanted models, the pagination links disappear. I have tried setting the pagination on my new dataProvider but nothing works.
Here's my code in the controller action:
$request = Yii::$app->request;
$search_model = new StaffEmploymentListViewSearch();
$data_provider = $search_model->search($request->queryParams);
$models = $data_provider->models;
for($k=0;$k<count($models);$k++)
{
if($models[$k]->employ === null){
unset($models[$k]);
}
}
$config = [
'pageParam' => 'page',
'pageSizeParam' => 'per-page',
'forcePageParam' => true,
'route' => null,
'params' => null,
'urlManager' => null,
'validatePage' => true,
'totalCount' => 5214,
'defaultPageSize' => 20,
'pageSizeLimit' => [
'0' => 1,
'1' => 50
],
'pagesize' => 20
];
$data_provider->setModels($models);
$data_provider->setPagination($config);
return $this->render('all-staff',[
'dataProvider' => $data_provider,
'searchModel' => $search_model
]);
Here's my search method:
$query = StaffEmploymentListView::find()
->SELECT([
'PAYROLL_NO',
'BIRTH_DATE',
"ADD_MONTHS(BIRTH_DATE, 70 * 12) AS RETIRE_DATE"
]);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => false,
'pagination' => [
'pagesize' => 20,
],
]);
How do I go about doing this?
Try to use ArrayDataProvider
$query = StaffEmploymentListView::find()
->select([
'PAYROLL_NO',
'BIRTH_DATE',
"ADD_MONTHS(BIRTH_DATE, 70 * 12) AS RETIRE_DATE"
]);
$allModels = [];
foreach ($query->all as $staffEmployment)
{
if ($model->employ === null){
$allModels[] = $model;
}
}
$dataProvider = new ArrayDataProvider([
'allModels' => $allModels,
'pagination' => [
'pageSize' => 20,
],
'sort' => false
]);
return $this->render('all-staff',[
'dataProvider' => $data_provider,
'searchModel' => $search_model // ???
]);
I've createCommand in controller
$receipts=new receipts();
$query1 = new Query;
$query1 ->select(['price','date','id'])
->from('paymentreceipts')
->join( 'INNER JOIN','patient','patient.patient_id =paymentreceipts.patient_id' )
->where('patient.patient_id=:id', array(':id'=>$id))
->orderby ('paymentreceipts.date');
$command1 = $query1->createCommand();
$dataProvider1 = $command1->queryAll();
$gridViewDataProvider3 = new \yii\data\ArrayDataProvider([
'allModels' => $dataProvider1,
'sort' => [
'attributes' => ['price','reg_date','id'],
],
]);
return $this->render('view', [
'model' => $this->findModel($id),
'gridViewDataProvider2' => $gridViewDataProvider2,
]);
in view.php
<?=
GridView::widget([
'dataProvider' => $gridViewDataProvider2,
// 'pjax'=>true,
'summary'=>'',
'showFooter' => true,
'columns' => [
['label' => 'رقم الخدمة',
'attribute' => 'id',
],
[
// 'label'=>'url',
'format' => 'raw',
'value'=>function ($data) {
return Html::a('$data->date','#',['class' => 'receipts','id'=>'id']);
},
],
]
]) ?>
what i need is : add the id in 'attribute' => 'id' number to the link that i created here ['class' => 'receipts','id'=>'id']);
i used 'id'=> $gridViewDataProvider2->id but it doesn't work !
My English is not good , so maybe my question not be clear .
JOIN statement is the reason why you don't receive "id". Because both of your tables have "id" column and it becomes ambiguous to read it. Change you query like below,
$query1 ->select(['price','date','id as receiptId'])
->from('paymentreceipts')
->join( 'INNER JOIN','patient','patient.patient_id =paymentreceipts.patient_id' )
->where('patient.patient_id=:id', array(':id'=>$id))
->orderby ('paymentreceipts.date');
$command1 = $query1->createCommand();
and then you can make the link like below.
return Html::a('$data->date','#',['class' => 'receipts','id'=>$data->receiptId]);
If I have 2 fields in db - probability and influence and I need a column in GridView where these two fields are multiplied. I managed to add it there like:
[
'attribute' => 'priority',
'format' => 'raw',
'value' => function ($model) {
return $model->influence * $model->probability;
},
],
But can't handle the sorting, because that column is not in db and adding filters to $query causes only errors.
$query = Risks::find();
$query->select(`probability*influence AS priority`);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
Updated (works Asc and Desc but not with filters)
public function search($params)
{
$query = Risks::find();
$query->joinWith(['author', 'proj']);
$query->select('*, (probability * influence) as priority');
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->setSort([
'attributes' => [
// 'id',
'probability',
'risks',
'influence',
'del' => [
'asc' => ['risks.del' => SORT_ASC],
'desc' => ['risks.del' => SORT_DESC],
],
'priority' => [
'asc' => ['priority' => SORT_ASC],
'desc' => ['priority' => SORT_DESC],
'label' => 'Priority',
],
'proj' => [
'asc' => ['projects.name' => SORT_ASC],
'desc' => ['projects.name' => SORT_DESC],
],
'author' => [
'asc' => ['users.name' => SORT_ASC],
'desc' => ['users.name' => SORT_DESC],
]
]
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
'proj_id' => $this->proj_id,
'author_id' => $this->author_id,
'influence' => $this->influence,
'probability' => $this->probability,
//'del' => $this->del,
])
->andFilterWhere(['like', 'projects.name', $this->proj])
->andFilterWhere(['like', 'users.name', $this->author]);
$query->andFilterWhere(['like', 'risks', $this->risks]);
$query->having('priority = '. $this->priority);
//$query->having(['priority' => $this->priority]);
return $dataProvider;
}
STEP 1: Add a getter function to your base Risks model:
public function getPriority() {
return ($this->probability * $this->influence);
}
STEP 2: Add an attribute priority to your model RisksSearch and configure your rules.
/* your calculated attribute */
public $priority;
/* setup rules */
public function rules() {
return [
/* your other rules */
[['priority'], 'safe']
];
}
STEP 3: Edit the search() method to include the calculated field priority
public function search($params) {
$query = Person::find();
$query->select('*, (probability * influence) as priority');
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
/**
* Setup your sorting attributes
* Note: This is setup before $this->load($params)
*/
$dataProvider->setSort([
'attributes' => [
'id',
'priority' => [
'asc' => ['priority' => SORT_ASC],
'desc' => ['priority' => SORT_DESC],
'label' => 'Priority',
'default' => SORT_ASC
],
]
]);
...
STEP 4: Add $query->andFilterWhere() after $this->load($params) to be able to filter the calculated field
// use the operator you wish, i.e. '=', '>', '<' etc
$query->andFilterWhere(['=', '(probability * influence)', $this->priority]);
Removed
$query->select('*, (probability * influence) as priority');
changed
'priority' => [
'asc' => ['(probability * influence)' => SORT_ASC],
'desc' => ['(probability * influence)' => SORT_DESC],
'label' => 'Priority',
],
and after $this->load($params);
$query->andFilterWhere(['=', '(probability * influence)', $this->priority]);
And search works as needed! :)
Thanks for help!
Here is my solution, which works for sorting non-table field
$dataProvider->sort->attributes['customer'] = [
'asc' => ['customer' => SORT_ASC],
'desc' => ['customer' => SORT_DESC],
];
I have an array of data very similar to this
[
'name'=>'mark',
'age'=> '21'
'height'=> '190 cm'
]
I searched Google and all the results i found were using an active record object.
How do i use the gridview with an array of this sort?
You should use ArrayDataProvider (https://github.com/yiisoft/yii2/blob/master/framework/data/ArrayDataProvider.php)
$provider = new ArrayDataProvider([
'allModels' => $yourArray,
'sort' => [
'attributes' => ['id', 'username', 'email'],
],
'pagination' => [
'pageSize' => 10,
],
]);
In Yii 1.1 this code works for default sorting:
$dataProvider = new CActiveDataProvider('article',array(
'sort'=>array(
'defaultOrder'=>'id DESC',
),
));
How default sorting can be set in Yii2?
Tried below code, but no result:
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['defaultOrder'=>'topic_order asc']
]);
I think there's proper solution. Configure the yii\data\Sort object:
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort'=> ['defaultOrder' => ['topic_order' => SORT_ASC]],
]);
Official doc link
Or
$dataProvider->setSort([
'defaultOrder' => ['topic_order'=>SORT_DESC],
'attributes' => [...
defaultOrder contain a array where key is a column name and value is a SORT_DESC or SORT_ASC that's why below code not working.
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['defaultOrder'=>'topic_order asc']
]);
Correct Way
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => [
'topic_order' => SORT_ASC,
]
],
]);
Note: If a query already specifies the orderBy clause, the new ordering instructions given by end users (through the sort configuration) will be appended to the existing orderBy clause. Any existing limit and offset clauses will be overwritten by the pagination request from end users (through the pagination configuration).
You can detail learn from
Yii2 Guide of Data Provider
Sorting By passing Sort object in query
$sort = new Sort([
'attributes' => [
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
'default' => SORT_DESC,
'label' => 'Name',
],
],
]);
$models = Article::find()
->where(['status' => 1])
->orderBy($sort->orders)
->all();
if you have CRUD (index) and you need set default sorting your controller for GridView, or ListView, or more...
Example
public function actionIndex()
{
$searchModel = new NewsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
// set default sorting
$dataProvider->sort->defaultOrder = ['id' => SORT_DESC];
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
you need add
$dataProvider->sort->defaultOrder = ['id' => SORT_DESC];
Try to this one
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$sort = $dataProvider->getSort();
$sort->defaultOrder = ['id' => SORT_ASC];
$dataProvider->setSort($sort);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort'=> ['defaultOrder' => ['iUserId'=>SORT_ASC]]
]);
As stated in the guide, you must specify the sorting behaviors of a data provider by configuring its sort properties which correspond to the configurations for yii\data\Sort
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort'=> ['defaultOrder' => ['topic_order' => SORT_ASC]],
]);
$modelProduct = new Product();
$shop_id = (int)Yii::$app->user->identity->shop_id;
$queryProduct = $modelProduct->find()
->where(['product.shop_id' => $shop_id]);
$dataProviderProduct = new ActiveDataProvider([
'query' => $queryProduct,
'pagination' => [ 'pageSize' => 10 ],
'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]]
]);
you can modify search model like this
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => ['user_id ASC, document_id ASC']
]
]);