I'm new to Drupal 8 and I'm trying to create a form that allow to fetch my content types hierarchy and show its fields using ajax callback, but unfortunately none of the fields shows up eventhough the ajax works fine and callback function correctly fired? The Fields Types in my ContentType is {body:text_with_summary, price:decimal, title:string} As I Tried with debugging it seems that my code cannot define those types as form field types

here is my code in MyForm.php File:

public function level3SelectedCallback(array &$form, FormStateInterface $form_state) {
    $ajax_response = new AjaxResponse();
    $fields = MyController::contentTypeFields('MY_VOC');

    foreach ($fields as $field){
        $name = $field->id();
        $label = $field->label();
        $type = $field->getType();
        $desc = $field->getDescription();
        $form['fields_wrapper']['field_'.$label] = array(
            '#type' => $type,
            '#description' => $desc,
            //'#options' => '',
            '#attributes' => array(
                'class' => array(
        $ajax_response->addCommand(new HtmlCommand('#fields-wrapper', $form['fields_wrapper']['field_'.$label]));


    $ajax_response->addCommand(new InvokeCommand('#fields-wrapper', 'change'));

    return $ajax_response;

My Controller Function is:

static function contentTypeFieldsAsFields($contentType) {
    // Get the definitions
    $fields = array_filter(
            \Drupal::service('entity.manager')->getFieldDefinitions('node', $contentType), function ($field_definition) {
                return $field_definition instanceof \Drupal\field\Entity\FieldConfig;
    return $fields;

3 Answers 3


To get an empty form of a content type you would use code like this:

$node = \Drupal\node\Entity\Node::create(['type' => 'page']);
$form = \Drupal::service('entity.form_builder')->getForm($node);

To open this form with ajax, put the form in a controller:

public function contenttypeform(NodeTypeInterface $node_type) {
    $node = $this->entityTypeManager()->getStorage('node')->create([
      'type' => $node_type->id(),
    return $this->entityFormBuilder()->getForm($node);

Configure a route for this controller and open the form in an ajax modal like this example from ConfigSync.php:

$links['view_diff'] = array(
            '#type' => 'link',
            'title' => $this->t('View differences'),
            'url' => Url::fromRoute($route_name, $route_options),
            'attributes' => array(
              'class' => array('use-ajax'),
              'data-dialog-type' => 'modal',
              'data-dialog-options' => json_encode(array(
                'width' => 700
  • Great But yes I want to do this in D8 specifically in ajax callback Aug 18, 2016 at 20:11
  • I don't think that this can work, but you could use a modal dialog with ajax, see the edited answer.
    – 4uk4
    Aug 18, 2016 at 21:00

Thanks @4k4 for your great help but I've solved it how to use it in drupal 8 here is my FormBuild code but unfortunately not all fields shown just the title and there is the warning shown in console:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. VM3435:19 [CKEDITOR] Error code: editor-incorrect-destroy. VM3435:19 [CKEDITOR] For more information about this error go to http://docs.ckeditor.com/#!/guide/dev_errors-section-editor-incorrect-destroy

and here is my Form Build Code:

$form['fields_wrapper'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'fields-wrapper', 'class' => ['hiddenselect']],

    if ($form_state->getValue('level1') != false) {
        $val = $form_state->getValue('level1');
        $this->fields = MY_Controller::contentTypeFieldsAsFields($val);
        $node = \Drupal\node\Entity\Node::create(['type' => $val]);
        $myform = \Drupal::service('entity.form_builder')->getForm($node);

        foreach ($this->fields as $field) {
            //$name = $field->id();
            $n = $field->getName();
            $form['fields_wrapper'][$n] = $myform[$n];

and here is my ajax callback code:

public function level1SelectedCallback(array &$form, FormStateInterface $form_state) {
    // Instantiate an AjaxResponse Object to return.
    $ajax_response = new AjaxResponse();
    $val = $form_state->getValue('level1');

    foreach ($this->fields as $field) {
        $n = $field->getName();
        $ajax_response->addCommand(new HtmlCommand('#fields-wrapper', $form['fields_wrapper'][$n]));
    $ajax_response->addCommand(new InvokeCommand('#fields-wrapper', 'change'));


    return $ajax_response;



It will give all fields related to content type.


  • I'm using it in my controller function as the last piece of code in my Question after edit it: Aug 18, 2016 at 11:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.