Meteor-Community-Packages / meteor-autoform

AutoForm is a Meteor package that adds UI components and helpers to easily create basic forms with automatic insert and update events, and automatic reactive validation.
MIT License
1.44k stars 328 forks source link

[Discussion] Separating themes as packages #669

Closed delgermurun closed 3 years ago

delgermurun commented 9 years ago

How about that?

Most of apps use one of integrated themes or even use none of them. So apps load plenty of unused codes on client.

aldeed commented 9 years ago

Yes, already planning to do this. There is actually only one theme, bootstrap, currently built into the package, and a few minor variations of it. Need to get 5.0 released first and wait awhile till any issues with that are worked out. Then moving bootstrap to a separate pkg is next.

delgermurun commented 9 years ago

@aldeed Is plain not theme? :D

aldeed commented 9 years ago

Technically yes, but it's the fallback theme and it's handled a bit differently. If plain were removed nothing would appear, and I'd rather not require a theme pkg. I want things to work out of the box with just the single package.

jcheroske commented 9 years ago

When you do this, are you planning on making theme extension and modification more of a black-box experience? I've been creating some of my own templates, and I've noticed that unless I copy-and-paste some of the helpers and such from the bootstrap theme things don't work right. For example, the optionAtts helper that gets attached to 'select' elements needs to be transferred over to my new select template if I want to be able to override the 'option' list with different labels. This is not documented anywhere, and even if it was, it just doesn't seem like a clean, extensible architecture. My feeling about this library so far is that, as long as I stay within the lines, it's really nice and powerful, but once I start needing things near the edges, it quickly becomes difficult and confusing. Any help or suggestions are extremely welcome.

aldeed commented 9 years ago

Open to suggestions, but eventually I'm going to better document the customization and my plan is to recommend using inheritsHelpersFrom to inherit the helpers. I'm not sure there is any cleaner way. I already take care of all the shared, non-theme-specific things prior to invoking the theme templates, so helpers are needed only for adding classes like bootstrap does.

aldeed commented 9 years ago

btw, after I release 5.0 (soon), my plan is for 6.0 to be pretty much just this issue, pulling bootstrap theme into its own package. After that will be writing tests and setting up a good documentation site.

jcheroske commented 9 years ago

I totally get that you've got an uphill battle, with no formal template inheritance and such. That said, this is in the bootstrap3.js file:

var selectHelpers = {
  optionAtts: function afSelectOptionAtts() {
    var item = this;
    var atts = {
      value: item.value
    };
    if (item.selected) {
      atts.selected = "";
    }
    return atts;
  }
};
Template["afSelect_bootstrap3"].helpers(selectHelpers);
Template["afSelectMultiple_bootstrap3"].helpers(selectHelpers);
Template["afBooleanSelect_bootstrap3"].helpers(selectHelpers);

That helper doesn't seem to be bootstrap specific, but without it the 'options' label override breaks.

aldeed commented 9 years ago

It's not bootstrap specific but it's template specific. I'm bothered a bit by that one, too. Maybe we could at least pull that out as a global template named afOptionAtts or something since it's used in many places pretty much identically. I'll look into it.

jcheroske commented 9 years ago

Since we're talking, here's my two cents... There needs to be a giant abstraction boundary between form state and logic, and form look and feel. Maybe even separate modules. The core should provide helpers for all form and field states (dirty, valid, etc.), should provide block helpers to loop over nested elements, and should provide a simple syntax for referencing nested fields. Backing the form with a schema is fabulous and should remain. It should be possible to construct a complete form in a single file, with all of the form's markup declared there, and not using any other templates that include look-and-feel tags. No themes and no included templates with html tags anywhere unless they are used to create functionality, such as hidden fields, etc.

Maybe it's already possible to do all this stuff, and if so, then you should work up an example where a complete and rich form with nested objects and arrays is built without ever including any templates such as afInputText and afSelect. Instead use form and field state flags and loops such as afEachArrayItem to build it, and show how all the form fields and other markup can be simply declared right then and there.

To say it yet another way, what's needed, imho, are the conditionals, loops, variables, and a field reference syntax that allows a developer to close the impedance mismatch between forms and the data representation. As far as I can tell, Meteor does not have this yet. Autoform is seemingly close to achieving this, but feels a bit confused about its priorities. Themes and one-line generation of forms are nice, but they are not essential functions.

aldeed commented 9 years ago

@jcheroske, maybe you can create an example of what you would want my example to look like because I'm not sure I'm fully understanding. It sounds like you're describing what autoform already is, but if I can see an example of what you're expecting, I can better respond.

AutoForm has always been primarily about generating complex forms with automatic validation. The quickForm stuff was a small part of it until a million people started asking for features to make things more automatic and magical. If you want to write out the whole form, then you just do that. If you don't, then you use quickForms and make theme templates, etc.

jcheroske commented 9 years ago

Check out issue #708 too. It kinda points at what I'm asking for.

Here is an example using an idealized syntax, based off of autoform. Maybe it already can do what I'm asking, but I'm just clueless (highly likely) or maybe it could get to this point with just a small amount of work (also highly likely).

{{# autoForm collection="Contacts" id="insertContactForm" type="insert" validation="keyup"}}

<div class="{{#if afFieldIsDirty field="name"}}{{#if afFieldIsValid field="name"}}success{{else}}error{{/if}}{{/if}}">
  <label>{{afFieldLabel field="name"}}</label>
  {{> afFieldInput name="name"}}
  <span>{{afFieldMessage name="name"}}</span>
</div>

{{# afEachArrayItem name="methods"}}

 <!-- Logic: Toggle the display of the email and phone fields based on the selected value in 'type'.
        Only apply the 'success' or 'error' styles once the form has been touched. -->
<div class="
   {{#if afFieldValueIs field="methods.$.type" value="email"}}
    {{#if afFieldIsDirty field="methods.$.email"}}
      {{#if afFieldIsValid field="methods.$.email"}}success{{else}}error{{/if}}
    {{/if}}
  {{/if}}

  {{#if afFieldValueIs field="methods.$.type" value="phone"}}
    {{#if afFieldIsDirty field="methods.$.phone"}}
      {{#if afFieldIsValid field="methods.$.phone"}}success{{else}}error{{/if}}
    {{/if}}
  {{/if}}
">

  {{> afFieldInput name="methods.$.type"}}

  {{#if afFieldValueIs field="methods.$.type" value="email"}}
    {{> afFieldInput name="methods.$.email"}}
    <span>{{afFieldMessage name="methods.$.email"}}</span>
  {{/if}}

  {{#if afFieldValueIs field="methods.$.type" value="phone"}}
    {{> afFieldInput name="methods.$.phone"}}
    <span>{{afFieldMessage name="phone"}}</span>
  {{/if}}

{{/afEachArrayItem}}
{{/autoForm}}