phpyiiyii2gii

Yii2 Gii : Add autocomplete and class name generation to custom template


I recently began creating my own Gii templates, in this case, for CRUD.

Now I noticed, when creating a Model with Gii you have an autocomplete for the table name and, after this is selected, the Model class name is automatically generated as well.

How do I implement this behavior for my CRUD templates as well? I have already created a custom CRUD generator for my template:

namespace app\templates\gii\crud\custom;

class Generator extends \yii\gii\generators\crud\Generator
{
    // ...
}

What do I have to include to:

  1. Include autocomplete to select an existing Model class to create the CRUD operations for

  2. Automatically generate the SearchModel name based on the previously selected Model class (e.g. app\model\CategoryModel becomes app\model\CategorySearchModel)


Solution

  • After being unable to include the autocompletion in the generator itself, I build a workaround with Javascript.

    Important: This solution assumes you are using the yii advanced template and are using Gii from the backend app. You will need to adjust the code if this is not the case

    First of all, I included my JS script in gii/templates/crud/form.php, note that this destination may vary from yours, depending where you have set up your Gii templates.

    \backend\assets\CrudAutocompleteAsset::register($this);
    
    echo $form->field($generator, 'templateDestination')->dropDownList([
        "backend" => "Backend",
        "frontend" => "Frontend"
    ]);
    

    You will also need to include the public property templateDestination to your Generator class. If you do not use the advanced template, neither this nor the select field will be necessary. You will only need the Asset then. If you don't know how to use assets, check out the Yii2 guide about Assets

    /**
     * Destination namespace of generated code for advanced yii template
     * @var string
     */
    public $templateDestination = "backend";
    

    The Asset CrudAutocompleteAsset will ad my js file. I've made a sample on JS fiddle

    $(document).ready(function () {
    
        var templateDestinationSelect = $("select[name='Generator[templateDestination]']");
        var modelClassInput = $("input[name='Generator[modelClass]']");
        var searchModelClassInput = $("input[name='Generator[searchModelClass]']");
        var controllerClassInput = $("input[name='Generator[controllerClass]']");
        var viewPathInput = $("input[name='Generator[viewPath]']");
    
        modelClassInput.change(function () {
            var destination = templateDestinationSelect.val();
            var modelClass = $(this).val();
            var modelNs = modelClass.substr(0, modelClass.lastIndexOf("\\"));
            var targetNs = destination + modelNs.substr(modelNs.indexOf("\\"));
            var modelClassName = modelClass.substr(modelClass.lastIndexOf("\\") + 1);
            var modelViewName = modelClassName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
    
            var modelSearchClass = modelNs + "\\" + modelClassName + "Search";
            searchModelClassInput.val(modelSearchClass);
    
            var controllerClassName = targetNs.replace("models", "controllers") + "\\" + modelClassName + "Controller";
            controllerClassInput.val(controllerClassName);
    
            var viewPath = "@app/../" + destination + "views/" + modelViewName;
            viewPathInput.val(viewPath);
    })