Reputation: 1469
I have an object, Object1
, that references Object2
in a one-to-many relationship: one Object1
to many Object2
.
In my Object1
view, I am trying to include a yii\grid\GridView
of the related Object2
items only. Not in addition to the Object1
data. Just a GridView
of Object2
items only.
Using code like that below, I believe I have to set both $dataProvider
and $searchModel
in my controller but I'm not sure how to link Yii::$app->request->queryParams
with $id
.
My code just returns all Object2
items, regardless of their relationship with Object1
, which although makes perfect sense to me, is not what I'm looking for.
I am not even sure that this is the correct approach. Does anyone know of a solution? Thanks in advance.
/* Object1 model */
public function getRelations() {
return $this->hasMany(Object2::className(), ['relation' => 'id']);
}
/* Object1 view */
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'attr1',
'attr2',
'attr3',
'attr4',
['class' => 'yii\grid\ActionColumn'],
],
]);
/* Object1 controller */
public function actionView($id){
$searchModel = new Object2Search();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('view', [
'model' => $this->findModel($id),
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
Upvotes: 1
Views: 1559
Reputation: 33548
Instead of rendering GridView in detail view I can suggest alternative approach.
Create a separate regular GridView
widgets for both Object1
and Object2
items.
Extend ActionColumn
of Object1
GridView with additional link to related items. I already explained it here, but I also include code here for better understanding:
[
'class' => 'yii\grid\ActionColumn',
'template' => '{objects2} {view} {update} {delete}',
'buttons' => [
'objects2' => function ($url, $model, $key) {
/* @var $model common\models\Object1 */
return Html::a(
'<span class="glyphicon glyphicon-arrow-down"></span>',
['objects2/index', 'object1_id' => $model->id],
[
'title' => 'Objects 2',
'aria-label' => 'Objects 2',
'data-pjax' => '0',
]
);
},
],
],
Modify index
action of Object2Controller
to accept additional parameter (Object 1 id):
/**
* @param integer $object1_id
* @return string
* @throws \yii\web\NotFoundHttpException
*/
public function actionIndex($object1_id)
{
$searchModel = new Object2Search;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
search()
method of Object2Search
should also handle additional parameter:
/**
* @param array $params
* @return ActiveDataProvider
*/
public function search($params)
{
$query = Object2::find()->where(['object1_id' => $params['object1_id']]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
// Additional filters
return $dataProvider;
}
Make sure to not include object1_id
in rules()
and additional filters.
As for display of Object2
items, simply exclude object1_id
column and you are done.
Obviously this can be customized more, it's just a basic example.
The main advantage of this approach is code for models of different type is separated and easier to maintain.
As for using it in detail view, modify search()
method of Object2Search
model to apply initial filter by object1_id
as I described above, but in this case pass id
parameter from query params (which comes from view
action):
$query = Object2::find()->where(['object1_id' => $params['id']]);
Use partials for GridView
for better views organization.
Upvotes: 1