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

Proper way to make custom input value reactive? #1678

Closed TitaniteSlab closed 3 years ago

TitaniteSlab commented 5 years ago

The following afFieldValueIs helpers are not reactively updating based on the value of my custom afRadioButtons inputType. It works for the boolean-checkbox type in the same form.

How do I get mine working reactively? I'm not understanding how AutoForm reacts to changes to custom input type values? Is it looking at the data-schema-key DOM somehow??

Using AutoForm 6.3.0

Custom Input Template:

<template name="afRadioButtons">
    <div class="btn-group" {{dsk}}>
        {{#each item in items}}
            <button class="btn btn-white {{#if item.selected}}active{{/if}}" data-value="{{item.value}}" {{atts}}>
                {{#if item.iconClass}}<i class="{{item.iconClass}}"></i> {{/if}}
                {{item.label}}
            </button>
        {{/each}}
        {{#let message=(afFieldMessage name=this.afFieldInputAtts.name)}}
            {{#if message}}
                <span class="help-block">{{{message}}}</span>
            {{/if}}
        {{/let}}
        {{#if this.afFieldInputAtts.helptext}}
            <span class="help-block">{{this.afFieldInputAtts.helptext}}</span>
        {{/if}}
    </div>
</template>

Custom Input JS:

import './afRadioButtons.html';

AutoForm.addInputType('afRadioButtons', {
    template: 'afRadioButtons',
    valueOut: function () {
        return this.find('button.active').data('value');
    },
    contextAdjust: function (context) {
        let itemAtts = _.omit(context.atts);
        context.items = [];
        (context.selectOptions || []).forEach((opt) => {
            context.items.push({
                name: context.name,
                label: opt.label,
                value: opt.value,
                iconClass: opt.iconClass,
                _id: opt.value,
                selected: (opt.value === context.value),
                atts: itemAtts
            });
        });
        return context;
    }
});

Template.afRadioButtons.helpers({
    atts: function() {
        let atts = _.clone(this.atts);
        if (atts.hasOwnProperty('readonly')) {
            atts.disabled = 'disabled';
        }
        delete atts['data-schema-key'];
        return atts;
    },
    dsk: function() {
        return {
            'data-schema-key': this.atts['data-schema-key']
        };
    }
});

Template.afRadioButtons.events({
    'click button:not(disabled)': function(event, template) {
        event.stopPropagation();
        event.preventDefault();
        template.$('button').removeClass('active');
        $(event.currentTarget).addClass('active');
    }
});

AutoForm Template:

{{# autoForm
    id='myForm'
    type='method'
    schema=schema
    class='form-horizontal'
    meteormethod='myMethod'
    autocomplete='off'
    doc=doc 
}}
    {{> afQuickField name='custom_radio' template='bootstrap3-horizontal-helptext' label-class='col-sm-3' input-col-class='col-sm-9'}}
    {{#if (afFieldValueIs name='custom_radio' value='one')}}
        one is selected
    {{/if}}
    {{#if (afFieldValueIs name='custom_radio' value='two')}}
        two is selected
    {{/if}}

    {{> afQuickField name='bool' template='bootstrap3-horizontal-helptext' label-class='col-sm-3' input-col-class='col-sm-9'}}
    {{#if (afFieldValueIs name='bool' value=true)}}
        bool is true
    {{/if}}
    {{#if (afFieldValueIs name='bool' value=false)}}
        bool is false
    {{/if}}
{{/autoForm}}

Schema

let MySchema = new SimpleSchema({
    custom_radio: {
        type: String,
        label: 'Custom Radio',
        autoform: {
            type: 'afRadioButtons',
            options: [{
                label: 'One',
                value: 'one'
            },{
                label: 'Two',
                value: 'two'
            }],
            afFormGroup: {

            }
        },
        allowedValues: ['one', 'two']
    },
    bool: {
        type: Boolean,
        label: 'Bool',
        autoform: {
            type: 'boolean-checkbox'
        }
    }
}, {tracker: Tracker});