Skip to content

Field Configuration Modifiers #106

@robdmoore

Description

@robdmoore

This is a brainstorm of my idea for https://trello.com/c/1hNDoqon/74-ability-to-add-field-configuration-modifiers

It would probably replace the need for #102; I think this is more flexible and means we don't have to deal with crazy generic statics.

Thoughts @bendetat @MattDavies @zabulus?

// Create this class (happy to field better naming ideas)
public class FormFieldOutput<TModel, T>
{
    public FormFieldOutput(FieldParent parent)
    {
        Parent = parent;
    }

    public FieldParent Parent { get; private set; }

    public IFieldGeneratorHandler<TModel, T> Handler { get; set; }
    public IFieldConfiguration Configuration { get; set; }
    public IFormTemplate Template { get; set; }
    public ModelMetadata Metadata { get; set; }

    public ReadonlyFieldConfiguration GetReadonlyConfiguration()
    {
        return new ReadonlyFieldConfiguration(Configuration);
    }
}

// Change DefaultFieldGenerator.PrepareFieldConfiguration to:
        public FormFieldOutput<TModel, T> PrepareField(IFieldConfiguration fieldConfiguration, FieldParent fieldParent)
        {
            var field = new FormFieldOutput(fieldParent)
            {
                Handler = FieldGeneratorHandlersRouter<TModel, T>.GetHandler(this),
                Configuration = fieldConfiguration ?? new FieldConfiguration(),
                Template = Template,
                Metadata = Metadata
            }

            // This call could result in the handler, field config, template or metadata being changed on the fly for this field
            // In order to make things more testable / extendable we could put the conventions on the IForm object instead of in a static?
            FieldConventions.ForEach(c => c.Apply(field));

            field.Handler.PrepareFieldConfiguration(fieldConfiguration);
            field.Template.PrepareFieldConfiguration(this, handler, fieldConfiguration, fieldParent);

            return field;
        }

// These conventions will be defined by default (but can be removed), which were in the above method previously:
public class ReadonlyFieldsConvention : IFormConvention
{
    public void Apply<TModel, T>(FormFieldOutput<TModel, T> field)
    {
        if (field.IsReadOnly)
            field.Configuration.Readonly();
    }
}
public class FormatStringConvention : IFormConvention
{
    public void Apply<TModel, T>(FormFieldOutput<TModel, T> field)
    {
        if (!string.IsNullOrEmpty(field.Metadata.EditFormatString) && string.IsNullOrEmpty(field.Configuration.FormatString))
            field.Configuration.WithFormatString(field.Metadata.EditFormatString);
    }
}
public class NoneDisplayTextConvention : IFormConvention
{
    public void Apply<TModel, T>(FormFieldOutput<TModel, T> field)
    {
        if (!string.IsNullOrEmpty(field.Metadata.NullDisplayText) && string.IsNullOrEmpty(field.Configuration.NoneString))
            field.Configuration.WithNoneAs(field.Metadata.NullDisplayText);
    }
}

// And people can create and register their own conventions like this:

FieldConventions.Add(new AddCalendarToDateFieldsConvention());

...

public class AddCalendarToDateFieldsConvention : IFormConvention
{
    public void Apply<TModel, T>(FormFieldOutput<TModel, T> field)
    {
        if (typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTimeOffset))
            field.Configuration.AddClass("datepicker").WithFormatString("{0:dd/MM/yyyy}");
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions