Viewing & Updating model data with yii2-detail-view

About yii2-detail-view:

The yii2-detail-view extension (\kartik\detail\DetailView) offers you an easy way to EDIT and VIEW your model data, toggle these modes, and adds other features. You can read the extension documentation and/or view a demo of this extension, to understand usage.

This article explains how you can use the extension with additional settings to your controller and view objects. In addition, it explains how DetailView will work with the EDIT mode and trigger actions on the SAVE and DELETE buttons.

NOTE: To use the yii2-datecontrol extension with this widget, you can refer this article.

Scenario

Let’s say you have a database table named tbl_book with these columns:

id INT(11)
book_code VARCHAR(30)
synopsis TEXT
color VARCHAR(10)
publish_date DATE
status TINYINT(1)
sale_amount DECIMAL(11,2)
buy_amount DECIMAL(11,2)

Generate the Book model and CRUD through Gii.

Controller

After generating the CRUD, delete the actionUpdate method in your BookController.php. Incorporate these changes below:

actionView

Change the actionView method to work with the yii2-detail-view extension.

class BookController extends Controller
{
    public function actionView($id) {
        $model=$this->findModel($id);

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            Yii::$app->session->setFlash('kv-detail-success', 'Saved record successfully');
            // Multiple alerts can be set like below
            Yii::$app->session->setFlash('kv-detail-warning', 'A last warning for completing all data.');
            Yii::$app->session->setFlash('kv-detail-info', '<b>Note:</b> You can proceed by clicking <a href="#">this link</a>.');
            return $this->redirect(['view', 'id'=>$model->id]);
        } else {
            return $this->render('view', ['model'=>$model]);
        }
    }
}

actionDelete

You can modify your actionDelete as generated by Gii CRUD for AJAX Delete functionality offered by the DetailView.

use yii\helpers\Url;
use yii\base\InvalidCallException;
class BookController extends Controller
{
    public function actionDelete() {
        $post = Yii::$app->request->post();
        if (Yii::$app->request->isAjax && isset($post['custom_param'])) {
            $id = $post['id'];
            if ($this->findModel($id)->delete()) {
                echo Json::encode([
                    'success' => true,
                    'messages' => [
                        'kv-detail-info' => 'The book # ' . $id . ' was successfully deleted. <a href="' . 
                            Url::to(['/site/view']) . '" class="btn btn-sm btn-info">' .
                            '<i class="glyphicon glyphicon-hand-right"></i>  Click here</a> to proceed.'
                    ]
                ]);
            } else {
                echo Json::encode([
                    'success' => false,
                    'messages' => [
                        'kv-detail-error' => 'Cannot delete the book # ' . $id . '.'
                    ]
                ]);
            }
            return;
        }
        throw new InvalidCallException("You are not allowed to do this operation. Contact the administrator.");
    }
}

View

Edit your view file view.php to work with the yii2-detail-view extension.

use kartik\detail\DetailView;

$this->title='View Book'; // $model->name;
$this->params['breadcrumbs'][]=['label'=>'Books', 'url'=>['index']];
$this->params['breadcrumbs'][]=$this->title;

// setup your attributes
$attributes=[
    [
        'attribute'=>'book_code', 
        'format'=>'raw', 
        'value'=>'<kbd>'.$model->book_code.'</kbd>', 
        'displayOnly'=>true
    ],
    'attribute'=>'book_name',
    [
        'attribute'=>'color', 
        'format'=>'raw', 
        'value'=>Html::tag('span', ' ', [
            'class'=>'badge',
            'style'=>'background-color' . $model->color,
        ]) . '<code>' . $model->color . '</code>',
        'type'=>DetailView::INPUT_COLOR,
        'inputWidth'=>'40%'
    ],
    [
        'attribute'=>'publish_date', 
        'format'=>'date',
        'type'=>DetailView::INPUT_DATE,
        'widgetOptions'=>[
            'pluginOptions'=>['format'=>'yyyy-mm-dd']
        ],
        'inputWidth'=>'40%'
    ],
    [
        'attribute'=>'status', 
        'label'=>'Available?',
        'format'=>'raw',
        'value'=>$model->status ? 
            '<span class="label label-success">Yes</span>' : 
            '<span class="label label-danger">No</span>',
        'type'=>DetailView::INPUT_SWITCH,
        'widgetOptions'=>[
            'pluginOptions'=>[
                'onText'=>'Yes',
                'offText'=>'No',
            ]
        ]
    ],
    [
        'attribute'=>'sale_amount',
        'label'=>'Sale Amount ($)',
        'format'=>'double',
        'inputWidth'=>'40%'
    ],  
    [
        'attribute'=>'author_id',
        'format'=>'raw',
        'value'=>Html::a('John Steinbeck', '#', [
            'class'=>'kv-author-link'
        ]),
        'type'=>DetailView::INPUT_SELECT2, 
        'widgetOptions'=>[
            'data'=>ArrayHelper::map(
                Author::find()->orderBy('name')->asArray()->all(), 
                'id', 
                'name'
            ),
            'options'=>['placeholder'=>'Select ...'],
            'pluginOptions'=>['allowClear'=>true]
        ],
        'inputWidth'=>'40%'
    ],
    [
        'attribute'=>'synopsis',
        'format'=>'raw',
        'value'=>'<span class="text-justify"><em>' . $model->synopsis . 
                 '</em></span>',
        'type'=>DetailView::INPUT_TEXTAREA, 
        'options'=>['rows'=>4]
    ]
];

echo DetailView::widget([
    'model'=>$model,
    'attributes'=>$attributes,
    'deleteOptions'=>[ // your ajax delete parameters
        'params' => ['id' => $model->id, 'custom_param' => true],
    ],
]);

That’s it, now when you browse to <your-base-domain>/book/view?id=<id> you should be able to update, save, and delete your records.

18 thoughts on “Viewing & Updating model data with yii2-detail-view

  1. Hello…Thanks for great extension…
    But i am not able to use FileInput with image preview…
    Can you give example for FileInput..?

    1. For view mode setting – explode the array and set this to display in the value setting for the attribute.

      For edit mode setting – use a dropdown list.

  2. Hello there
    I tried to use this code, modifying the forms obtained from the “Kartik CRUD Generator” but the delete action didn’t work for me. Using the inspector, I never saw traffic going out when I click the “Delete” button.

    Inspecting the Kartik Demo Page in http://demos.krajee.com/detail-view-demo, I noticed that when the Trash Icon gets clicked, it uses the /assets/prod/all-krajee.js, but inspecting my form, it uses /assets/random_number/yii.js

    I think that probably that’s the reason for not calling the ajax behavior in my local form…

    Any advice in the right direction, please?

  3. hi, got an issue with {buttons}, added them to mainTemplate, but they don’t work. clicking them doesn’t trigger anything, maybe there something i missed?

  4. Hi, thanks for the awesome widget! Can you help me with one little problem? I have an issue when rendering a partial view with the widget in another controller view – widget sends update POST on the URL of a base view. Do you have a smooth solution for that situation?

  5. Hi Kartik,
    i have a problem to update a hidden attribute i.e. when user modifies the view his ID will also be updated.

    [‘attribute’=>’user_id’,
    ‘format’=>’raw’,
    ‘value’=>”.$model->user->username.”,
    ‘type’=> DetailView::INPUT_HIDDEN,
    ‘displayOnly’=>true,
    ],
    With actionUpdate it was very intuitive but what about in actionView()?
    public function actionUpdate($id)
    {
    $model = $this->findModel($id);
    $model->user_id=Yii::$app->user->id;
    ….
    Hope you can help.
    Thanks.

  6. I create a multi DetailView of $model that have “array value” (using find()->all() instead findOne()). Could you give me any example how to performed edit mode on the controller? Because when I tried code above, I got this error “Call to a member function load() on a non-object”.
    Thank you for your help.

Comments are closed.