formio / formio.js

JavaScript powered Forms with JSON Form Builder
https://formio.github.io/formio.js
MIT License
1.89k stars 1.06k forks source link

[BUG] Adding custom templates #3178

Closed svenvandescheur closed 8 months ago

svenvandescheur commented 4 years ago

Trying to add a new custom component template according to https://github.com/formio/formio.js/wiki/Templates-API results in "Unknown template" error.

Environment

Steps to Reproduce

  1. Create a custom template similar to https://github.com/formio/formio.js/wiki/Templates-API#custom-component-templates (due to an error I need to extend my component from Components.components.base as imported Component did not do the trick).
  2. Make sure the custom template is used.
  3. Watch the result in the browser.
Templates.addTemplate('dummy', {
    form: `
        <div>
          <div ref="myref">
            {{ ctx.foo }}
            <div ref="mychild">1</div>
            <div ref="mychild">2</div>
            <div ref="mychild">3</div>
          </div>
        </div>
    `
});
render() {
    return super.render(this.renderTemplate('dummy', {}));
}

Expected behavior

I expect the template to show up in the browser.

Observed behavior

Unknown template: dummy is rendered.

Dummy is added as CSS framework to Template.templates instead:

{bootstrap: {…}, bootstrap3: {…}, semantic: {…}, dummy: {…}}

Replacing Templates.addTemplate('dummy', {...}) with Templates.templates.bootstrap.dummy (when bootstrap is the configured CSS framework) makes the template load correctly, but I guess that's not the correct way of adding a template.

Example

If possible, please provide a screenshot, live example (via JSFiddle or similar), and/or example code to help demonstrate the issue.

For code or form JSON, please enclose in a code block:

import {Templates, Components, Component} from 'formiojs';

const BaseComponent = Components.components.base;

Templates.addTemplate('dummy', {
    form: `
        <div>
          <div ref="myref">
            {{ ctx.foo }}
            <div ref="mychild">1</div>
            <div ref="mychild">2</div>
            <div ref="mychild">3</div>
          </div>
        </div>
    `
});

// Templates.templates.bootstrap.dummy = {
//     form: "foo bar",
// };

export default class DummyComponent extends BaseComponent {
    static schema() {
        return BaseComponent.schema({
            type: 'dummy',
        });
    }

    static get builderInfo() {
        return {
            title: 'Dummy',
            schema: DummyComponent.schema()
        };
    }

    render() {
        console.log(Templates.templates);
        return super.render(this.renderTemplate('dummy', {}));
    }
}

Components.addComponent('dummy', DummyComponent);
Schermafbeelding 2020-08-24 om 17 43 26
randallknutson commented 4 years ago

This is usually a result of the formio.js library being included twice in the project. For example, if you are using a module, be sure to add an externals section like this: https://github.com/formio/contrib/blob/master/webpack.config.js#L14-L16

svenvandescheur commented 4 years ago

@randallknutson thanks for your reply. Just to rule out that I imported the module twice I copied the CDN example to jsfiddle and recreated the problem there:

https://jsfiddle.net/f8yLz4cq/1/

I get the exact same behaviour "Unknown template: dummy"

I did a little bit of digging and my guess (based on my little knowledge of the codebase) is that this is because addTemplates assigns the template to the structure (Templates.templates) storing the various frameworks, where (I think) it should assign to Templates.current, referencing the current framework instead.

https://github.com/formio/formio.js/blob/fa7650c362960f70088e666ebfd1f2a73ec7a982/src/templates/Templates.js#L12-L14

randallknutson commented 4 years ago

I think you are right. We don't frequently use the addTemplate method since we are usually adding multiple at the same time so the addTemplate doesn't appear to be correct. Could you submit a pull request to change it to current?

svenvandescheur commented 4 years ago

I've added apull request, I was unable to get the library to install locally (tried npm run build, then npm install /path/to/lib, which usually works, but I ran into issues) but I did manage to get the tests running and added a test to confirm the behaviour.

Gerald1973 commented 3 years ago

I installed the last version with npm i, but didn't work, so I use the following solution:

Templates.defaultTemplates['customlayoutfieldsetcomponent'] = {
  form: (ctx) => `
  <div style="height:100px; width:100px; background:#FF0000"
    <div ref="myref">
      ${ctx.foo}
      <div ref="mychild">1</div>
      <div ref="mychild">2</div>
      <div ref="mychild">3</div>
    </div>
  </div>
`,
};
daneformio commented 8 months ago

Closing this thread as it is outdated. Please re-open if it is still relevant. Thank you for your contribution!