2

Does anyone know how to override/extend the behavior of apos.schemas.field() to have it output custom HTML?

I've tried to implement a contact form doing it 'their way', however I am quite disappointed at what level of control Apostrophe CMS gives you over the markup that it outputs.

I would like to style my inputs with Bootstrap and also add some additional attributes to the inputs, but the apos.schemas.field method does not seem to accept any other parameter than the readOnly flag, so I was wondering if I could extend this method to accept an object instead, which would contain all the necessary data I need, i.e. class, data attributes etc.

VadimG
  • 509
  • 4
  • 12

1 Answers1

1

There are several ways you can do it.

If you want to change the output for all fields of a particular schema field type, you can override the appropriate template in lib/modules/apostrophe-schemas/views, such as string.html.

The standard version of that template imports macros.html and invokes schemas.string, et cetera, but you don't have to do that.

What you DO have to do is:

  1. Make sure your field's entire content is wrapped in an outer element with a data-name attribute, which is set to the schema field name. Including any label or other content that should be shown and hidden together with the input field.

  2. Make sure the field itself has a name attribute which is also set to the schema field name. This applies to most field types, see macros.html for unusual cases like the tag and join editors.

In general: the markup is yours to change but data- attributes and the name attribute must stay the same.

"What if I want the conventional formatting in Apostrophe's forms, and special formatting in my forms?" One way to do that is to set a style property on the field in your schema, like so:

{
  name: 'flavor',
  type: 'string',
  style: 'custom'
}

Then your string.html can look like this:

{%- import "macros.html" as schemas -%}
{% if (data.style == 'custom') %}
  {# Custom way #}
  <div data-name="{{ data.name }}">
    <h4>{{ data.label }}</h4>
    <input name="{{ data.name }}" />
  </div>
{% else %}
  {# Normal way #}
  {{ schemas.string(data) }}
{% endif %}

Notice that this makes the custom style available for any form on your site where you choose to use it when adding fields. Also note that you can use addFields to restate the definition of a standard field if you want to change, let's say, title to use a custom style.

"Where do I output the current value of the field?" You don't. The schema module javascript will set that on the fly, and read it as well, which is one reason why you must follow the data-name and name attribute conventions.

Tom Boutell
  • 7,281
  • 1
  • 26
  • 23
  • How do I override a template? By putting a template of my own into /lib/modules/apostrophe-schemas/views and give it the same name as the original? Or do I put it into /lib/modules/my-apostrophe-schemas/views? – VadimG Aug 27 '17 at 20:19
  • /lib/modules/apostrophe-schemas/views You'll be doing this quite a lot, for instance to create your own `show.html` and `index.html` templates for pieces pages. – Tom Boutell Aug 28 '17 at 19:37
  • The "my-" prefix is only needed for the symlinks in public/modules. It's there because javascript and CSS assets pushed to the browser don't replace, they extend (the old one gets pushed, your subclass gets pushed too after it). – Tom Boutell Aug 28 '17 at 19:38
  • string.html not overwrite the select options css with this solution.This solution is only work with inputs not all data.type. @TomBoutell - How can I provide custom style for select options? – Manish J Nov 03 '18 at 15:34
  • For the select element, use select.html, and so on for each field type. – Tom Boutell Nov 04 '18 at 17:07