4Z4T4R
4Z4T4R

Reputation: 2458

Where does the 'form-control' class get set when using autoForm, Bootstrap 4?

I am engineering a custom autocomplete type for the afQuickfield in my Meteor project. The issue I am having is that when I set the type="autocomplete" on the afQuickfield, the class="form-control" attribute is missing. For all other field types, it is included.

I grepped form-control across the entire codebases for meteor-autoform as well as the scss and js directories of the bootstrap library. I only see occurances in the changelog and class definitions in scss/css.

I could just include class="form-control" in the afQuickfield definition, but that's a monkey patch and I'm not a fan of cutting corners.

Can anyone help me understand how form-control gets assigned in autoForm fields?

Here's my custom autocomplete code (it's a WIP, so no judging!). I'm just hoping to start with a text element with the proper atts so I can build from there.

// autocomplete.js
AutoForm.addInputType('autocomplete', {
  template: 'afAutocomplete',
  valueOut: function () {
    return this.val()
  },
  valueConverters: {
    stringArray: AutoForm.valueConverters.stringToStringArray,
    number: AutoForm.valueConverters.stringToNumber,
    numberArray: AutoForm.valueConverters.stringToNumberArray,
    boolean: AutoForm.valueConverters.stringToBoolean,
    booleanArray: AutoForm.valueConverters.stringToBooleanArray,
    date: AutoForm.valueConverters.stringToDate,
    dateArray: AutoForm.valueConverters.stringToDateArray
  },
  contextAdjust: function (context) {
    context.atts.autocomplete = 'off'
    return context
  }
})

// autocomplete.html
<template name="afAutocomplete">
  <input type="text" value="{{this.value}}" {{this.atts}} />
</template>

Here's the code from the type="text" field for comparison.

// text.js
AutoForm.addInputType('text', {
  template: 'afInputText',
  valueOut: function () {
    return this.val()
  },
  valueConverters: {
    stringArray: AutoForm.valueConverters.stringToStringArray,
    number: AutoForm.valueConverters.stringToNumber,
    numberArray: AutoForm.valueConverters.stringToNumberArray,
    boolean: AutoForm.valueConverters.stringToBoolean,
    booleanArray: AutoForm.valueConverters.stringToBooleanArray,
    date: AutoForm.valueConverters.stringToDate,
    dateArray: AutoForm.valueConverters.stringToDateArray
  },
  contextAdjust: function (context) {
    if (typeof context.atts.maxlength === 'undefined' && typeof context.max === 'number') {
      context.atts.maxlength = context.max
    }
    return context
  }
})

// text.html
<template name="afInputText">
  <input type="text" value="{{this.value}}" {{this.atts}}/>
</template>

As you can see the two are practically identical, yet the autocomplete version is without the form-control class in the actual HTML output.

Any ideas?

Upvotes: 1

Views: 123

Answers (1)

Jankapunkt
Jankapunkt

Reputation: 8413

Actually this seems to be a follow-up bug from AutoForm, because it should already throw the following error, when including afInputText:

There are multiple templates named 'afInputText'. Each template needs a unique name

What about the missing form-control?

This is correct in itself, because there is no class attribute on the input within the afAutoComplete template.

AutoForm built-in input types have no class attributes, because they will be overridden by the themes.

For example the text input in the Bootstrap 4 theme looks currently like this:

<template name="afInputText_bootstrap4">
  <input type="text" value="{{this.value}}" {{attsPlusFormControlClass}}/>
</template>

which itself is defined as helper.

So how to safely define the template?

Since there may be one day, where you will move from Bootstrap 4 to Bootstrap 5 you can actually create your component + logic as defined above:

// autocomplete.js
AutoForm.addInputType('autocomplete', {
  template: 'afAutocomplete',
  valueOut: function () {
    return this.val()
  },
  valueConverters: {
    stringArray: AutoForm.valueConverters.stringToStringArray,
    number: AutoForm.valueConverters.stringToNumber,
    numberArray: AutoForm.valueConverters.stringToNumberArray,
    boolean: AutoForm.valueConverters.stringToBoolean,
    booleanArray: AutoForm.valueConverters.stringToBooleanArray,
    date: AutoForm.valueConverters.stringToDate,
    dateArray: AutoForm.valueConverters.stringToDateArray
  },
  contextAdjust: function (context) {
    context.atts.autocomplete = 'off'
    return context
  }
})
// autocomplete.html
<template name="afAutocomplete">
  <input type="text" value="{{this.value}}" {{this.atts}} />
</template>

and additionally create a separate template, that overrides the styling:

<template name="afAutocomplete_bootstrap4">
    <input type="text" class="form-control" value="{{this.value}}" {{attsPlusFormControlClass}} />
</template>

Important here is the combination of afAutocomplete and _bootstrap4 which is used by AutoForm to determine the current template, as long as either the default template is set to bootstrap4 or the current form uses bootstrap4 as theme.

Upvotes: 1

Related Questions