protected function makeFormField($name, $config = [])
    {
        $label = $config['label'] ?? null;
        list($fieldName, $fieldContext) = $this->getFieldName($name);

        $field = new FormField($fieldName, $label);

        if ($fieldContext) {
            $field->context = $fieldContext;
        }

        $field->arrayName = $this->arrayName;
        $field->idPrefix = $this->getId();

        /*
         * Simple field type
         */
        if (is_string($config)) {
            if ($this->isFormWidget($config) !== false) {
                $field->displayAs('widget', ['widget' => $config]);
            }
            else {
                $field->displayAs($config);
            }
        }
        /*
         * Defined field type
         */
        else {
            $fieldType = $config['type'] ?? null;
            if (!is_string($fieldType) && $fieldType !== null) {
                throw new ApplicationException(Lang::get(
                    'backend::lang.field.invalid_type',
                    ['type' => gettype($fieldType)]
                ));
            }

            /*
             * Widget with configuration
             */
            if ($this->isFormWidget($fieldType) !== false) {
                $config['widget'] = $fieldType;
                $fieldType = 'widget';
            }

            $field->displayAs($fieldType, $config);
        }

        /*
         * Set field value
         */
        $field->value = $this->getFieldValue($field);

        /*
         * Apply the field name to the validation engine
         */
        $attrName = implode('.', HtmlHelper::nameToArray($field->fieldName));

        if ($this->model && method_exists($this->model, 'setValidationAttributeName')) {
            $this->model->setValidationAttributeName($attrName, $field->label);
        }

        /*
         * Check model if field is required
         */
        if ($field->required === null && $this->model && method_exists($this->model, 'isAttributeRequired')) {
            // Check nested fields
            if ($this->isNested) {
                // Get the current attribute level
                $nameArray = HtmlHelper::nameToArray($this->arrayName);
                unset($nameArray[0]);

                // Convert any numeric indexes to wildcards
                foreach ($nameArray as $i => $value) {
                    if (preg_match('/^[0-9]*$/', $value)) {
                        $nameArray[$i] = '*';
                    }
                }

                // Recombine names for full attribute name in rules array
                $attrName = implode('.', $nameArray) . ".{$attrName}";
            }

            $field->required = $this->model->isAttributeRequired($attrName);
        }

        /*
         * Get field options from model
         */
        $optionModelTypes = ['dropdown', 'radio', 'checkboxlist', 'balloon-selector'];
        if (in_array($field->type, $optionModelTypes, false)) {

            /*
             * Defer the execution of option data collection
             */
            $field->options(function () use ($field, $config) {
                $fieldOptions = $config['options'] ?? null;
                $fieldOptions = $this->getOptionsFromModel($field, $fieldOptions);
                return $fieldOptions;
            });
        }

        return $field;
    }