Relational data fields display and edit with the yii2-detail-view extension

You are viewing revision #8 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#7)

  1. Scenario
  2. Behavior in `yii\widgets\DetailView
  3. Behavior in `kartik\detail\DetailView
  4. Reasoning & Solution

If you have read this wiki you would be aware of the yii2-detail-view extension and how it offers you an easy way to EDIT and VIEW your model data, toggle these modes, and other features. You can read the extension documentation and/or view a demo of this extension, to understand usage.

Now if you are using the yii2-detail-view to display relational data, you must note that there is a slight difference in usage of attributes than in a normal yii detail-view.

Scenario

For example, let's consider you want to display the model Book in the detail view, which has an attribute author_id. The Book model has a relation named author to the author.name field linked via author_id.

Behavior in `yii\widgets\DetailView

For the core framework yii\widgets\DetailView, you can simply have the DetailView attributes set like below

'attributes' => [
    'id',
    'book_name', 
    'author.name'
]

Behavior in `kartik\detail\DetailView

However, in the yii2-detail-view extension, a configuration like above will throw the following exception.

Exception: The attribute 'author.name' is invalid. You cannot directly pass relational attributes in string format within '\kartik\widgets\DetailView'. Instead use the array format with 'attribute' property set to base field, and the 'value' property returning the relational data.

Reasoning & Solution

The yii2-detail-view is built to also display attributes for editing, and there is no base table attribute in the model called author.name. The solution to this is simple. Always use array format to pass such relational attributes. So the simple configuration for the kartik\detail\DetailView is the following:

'attributes' => [
  'id',
  'book_name', 
  [
    'attribute'=>'author_id',
    'value'=>$model->author->name,
    'type'=>DetailView::INPUT_SELECT2, 
    'widgetOptions'=>[
      'data'=>ArrayHelper::map(Author::find()->orderBy('name')->asArray()->all(), 'id', 'name'),
    ]
 ]

Now that should resolve both the VIEW and EDIT issues for you. With the above configuration, users would still see the author name instead of author_id in both VIEW and EDIT modes. In the EDIT mode, the above configuration will internally use the author_id to save data, but display the author names as a dropdown list using the \kartik\widgets\Select2 widget.