9

From working on plugin development, importing (I believe the correct term for this is macro) the 'forms' to quickly generate text areas, selects and etc. is incredibly useful. Adding the import now fails as '_includes' is only accessible from the control panel.

So in my template I could add this line:

{% import "_includes/forms" as forms %}

Then use something similar to this to output my forms fields?

{{ forms.textField({
    label: "First Name"|t,
    id: 'firstName',
    name: 'firstName',
    instructions: "First name (i.e John)",
    placeholder: "John",
    first: true,
    autofocus: true,
    required: true
}) }}

I know when using Symfony and Twig you can specify the namespace on where to grab the template from. Does Craft include a way to access those templates from the front end? Has anyone managed to perform this outside of the control panel?

Edit: if this is not possible, or p&t doesn't plan on making this possible (for security concerns) is there a way for a plugins template path to allow anonymous access? This way the developer could create an '_includes' and allow people to access it in the same manor?

4

We've done this on a few sites and you're right it's extremely helpful. The only way I've found to get it to work is to simply copy the "_includes/forms" folder from craft/app/templates to the sites craft/templates

It works but I'd love a less hacks way to do it, either through a plugin or some built-in means.

|improve this answer|||||
  • I thought symlinking the directory might work, but then subsequent imports get messed up :( – Tim Kelty Nov 19 '14 at 20:38
9

I've been able to render CP templates in the front end using some methods in PathService and TemplatesService, which you could use inside your own Template Variable to render the macros:

class YourVariable {

    public function renderFormMacro($macro, array $args)
    {
        // Get the current template path
        $originalPath = craft()->path->getTemplatesPath();

        // Point Twig at the CP templates
        craft()->path->setTemplatesPath(craft()->path->getCpTemplatesPath());

        // Render the macro.
        $html = craft()->templates->renderMacro('_includes/forms', $macro, array($args));

        // Restore the original template path
        craft()->path->setTemplatesPath($originalPath);

        return TemplateHelper::getRaw($html);
    }
}

Which would be used like:

craft.yourVariable.renderFormMacro('textField', { label: 'Name' })

I've not tested it but I think that should be close.

|improve this answer|||||
  • I'm going to have to give that a try soon, thanks Mike. – Jason McCallister Nov 20 '14 at 21:06
  • Confirming that it works. I think this is best answer – Yuri Salimovskiy Feb 26 '17 at 15:37
2

Here’s a Craft 3-friendly way of achieving what Mike suggested. This assumes your app already has a custom twig extension, if it doesn’t you can easily create one.

Add use craft\web\View; to the top of your TwigExtension, then in getFunctions() add your function definition:

new \Twig\TwigFunction('field', [$this, 'renderFormMacro'], ['is_safe' => ['html']]),

Then the function itself:

public function renderFormMacro(string $fieldType, array $fieldOptions) : string
{
    $oldMode = \Craft::$app->view->getTemplateMode();
    \Craft::$app->view->setTemplateMode(View::TEMPLATE_MODE_CP);
    $html = \Craft::$app->view->renderTemplateMacro('_includes/forms', $fieldType, [$fieldOptions]);
    \Craft::$app->view->setTemplateMode($oldMode);

    return $html;
}

You can then display fields in your frontend templates with code like this:

{{ field('text', {
    name: 'location',
    value: 'Timbuktu'
}) }}
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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