0

I've been checking for the past 2 days on how to do a drupal_get_form() for Drupal 8 and everyone seems to give me the following answers which don't seem to work. Let's just say I want to take the following Basic Page creation form and embed it into a Views header:

enter image description here

The ID of the form is: node-page-form or node_page_form if we were using drupal_get_form() from Drupal 7. But this time its the following:

$form = \Drupal::formBuilder()->getForm(Drupal\user\Form\NodePageForm::class);

I'm assuming "NodePageForm" is the parameter I'm suppose to use. If not how can one find this out from viewing the source of that page?

I then put the following PHP code in the Views header of my page like this:

enter image description here

I click save and update... my header is blank. What did I do wrong?

I'm trying to be as descriptive as I can explaining this problem. End result I just want to be able to take ANY form from any D8 page and be able to render it anywhere that takes PHP. That's my end goal. So no 3rd party modules as a solution.

9
  • Should not the PHP code exclude the <?php ?> tag?
    – avpaderno
    Commented Jul 28, 2016 at 21:33
  • I started writing an answer to this but it's getting out of hand, there's quite a bit of info to get across. Here's the first bit at least, hope it helps clear that part up: pastebin.com/hu2SrZiX
    – Clive
    Commented Jul 28, 2016 at 21:38
  • The first part of the second part included this: there isn't a way to identify the class that implements a form from its markup alone; you need to dig into the code. I'm pretty sure that holds true
    – Clive
    Commented Jul 28, 2016 at 21:39
  • So for Drupal 8 every time I see a form I'd like to render somewhere else I would need to do a grep in the codebase to find that form then look for the form_id? What would I need to grep for if thats the case? Commented Jul 28, 2016 at 21:46
  • @LittleCoding I did that if you looked at my code above. It doesn't work. I don't understand why its so difficult. All I want to do is find a form somewhere on the site and output it elsewhere in a PHP enabled text field. That is all. Apparently its more difficult that just D7's drupal_get_form() function method. Commented Jul 28, 2016 at 21:53

2 Answers 2

3

sEntity forms should be built using the entity.form_builder service. You'll need an entity to work with, for a node your code might change to something like this:

$node = \Drupal::entityTypeManager()
  ->getStorage('node')
  ->create(['type' => 'page']);

$form = \Drupal::service('entity.form_builder')->getForm($node);

print \Drupal::service('renderer')->render($form);

As noted in the comments, this won't actually work in the context you're using it, regardless of how you render the form. The views_php area handler renders the output of the custom PHP using #markup, which will strip out the <input> and other form tags. You'll need a custom or contributed module, or to alter the views_php module directly, to make this work.

Here's a simple area handler that adds support for common form tags:

<?php

namespace Drupal\foo\Plugin\views\area;

use Drupal\Component\Utility\Xss;
use Drupal\views_php\Plugin\views\area\ViewsPhp;

/**
 * Views area PHP text handler with support for common form tags.
 *
 * @ingroup views_area_handlers
 *
 * @ViewsArea("foo")
 */
class ViewsPhpForm extends ViewsPhp {

  public function render($empty = FALSE) {
    if (!$empty || !empty($this->options['empty'])) {
      $content = $this->renderViewsPhp($this->options['content']);
      $form_tags = ['form', 'input', 'select', 'fieldset', 'option', 'button', 'textarea', 'optgroup'];
      $allowed_tags = array_merge(Xss::getAdminTagList(), $form_tags);

      return [
        '#type' => 'inline_template',
        '#template' => Xss::filter($content, $allowed_tags),
      ];
    }

    return [];
  }

}

This code should be in src/Plugin/views/area/ViewsPhpForm.php and will need updating for the name of your module.

You'll also need to make views aware of it with a hook either in your .module file, or foo.views.inc:

/**
 * Implements hook_views_data().
 */
function foo_views_data() {
  $data['views']['php_with_form'] = [
    'title' => t('PHP with form'),
    'help' => t('Use PHP code with support for form tags.'),
    'area' => [
      'id' => 'foo',
    ],
  ];

  return $data;
}

After a cache rebuild you'll be able to add a new area handler, PHP with form, and your form should be rendered.

13
  • I tested your answer, but didn't work properly, this is what I got drt5a.ply.st/test
    – No Sssweat
    Commented Jul 28, 2016 at 23:46
  • Works well for me @NoSssweat: imgur.com/SM8uKIq, how are you rendering it?
    – Clive
    Commented Jul 28, 2016 at 23:50
  • 1
    It works it out from the entity, it's been set up with ->create(['type' => 'page']), that could just as easily by ->create(['type' => 'article']), and so on. I tested this by returning it from a controller (don't like turning on the PHP filter on principal!), where it works fine. But it makes sense that Views might push the output of the global header through a filter format. In fact that might be where this could be attacked, but it might mean making the default format more permissive. Not sure
    – Clive
    Commented Jul 29, 2016 at 0:04
  • 1
    It worked fine for me placing the code on a regular block. Looks like you're right, there is some sort of views filtering going on. I guess the OPer will have to use a regular block and place it before his view. PS: I also condone using/enableing PHP Filter on anything.
    – No Sssweat
    Commented Jul 29, 2016 at 0:13
  • 1
    Turns out it's the views_php module itself that's responsible, not Views @NoSssweat, I added a bit to the answer
    – Clive
    Commented Jul 29, 2016 at 0:28
1

See How to render form in drupal 8. Also has a link to the Change Record over on Drupal.org

2
  • Thats not the point. All I'm looking for is what is the exact code you need to just output / print a form that resides somewhere else on the site. Thats it. I've already checked that link. It doesnt work. Commented Jul 28, 2016 at 22:46
  • Then how about go at this from the opposite direction. Try hook_form_FORM_ID_alter to render your view as part of the form. Commented Jul 28, 2016 at 23:37

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.