Skip to content

Commit

Permalink
Working proof of concept for FluentForms.
Browse files Browse the repository at this point in the history
  • Loading branch information
rjygraham committed Sep 18, 2022
1 parent 5168607 commit 550339e
Show file tree
Hide file tree
Showing 33 changed files with 510 additions and 134 deletions.
129 changes: 54 additions & 75 deletions Maui.FluentForms/Builders/FormFieldBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@

namespace Maui.FluentForms.Builders;

internal class FormFieldBuilder<TModel, TProperty> : IFormFieldBuilder<TModel>,
public class FormFieldBuilder<TModel, TProperty> : IFormFieldBuilder<TModel>,
ICheckBoxFormFieldBuilder<TModel>,
ICustomTemplateFormFieldBuilder<TModel>,
IDatePickerFormFieldBuilder<TModel>,
IEditorFormFieldBuilder<TModel>,
IEntryFormFieldBuilder<TModel>,
Expand All @@ -18,184 +17,164 @@ internal class FormFieldBuilder<TModel, TProperty> : IFormFieldBuilder<TModel>,
ITimePickerFormFieldBuilder<TModel>

{
private readonly Expression<Func<TModel, TProperty>> expression;

private string controlTemplateName;

private IFormFieldConfiguration formFieldConfiguration;
private FormFieldLayoutConfiguration layoutConfiguration;
protected Expression<Func<TModel, TProperty>> Expression { get; init; }
protected string FormFieldTemplateName { get; set; }
protected IFormFieldConfiguration FormFieldConfiguration { get; set; }
protected FormFieldLayoutConfiguration LayoutConfiguration { get; set; } = new FormFieldLayoutConfiguration();

public FormFieldBuilder(Expression<Func<TModel, TProperty>> expression)
{
this.expression = expression;
this.Expression = expression;
}

public FormFieldBase Build(TModel model, IValidator<TModel> validator, int currentRow)
{
var field = CreateFormField(model, validator);
field.ApplyConfiguration(formFieldConfiguration);
field.ApplyLayoutConfiguration(layoutConfiguration, currentRow);
field.ApplyConfiguration(FormFieldConfiguration);
field.ApplyLayoutConfiguration(LayoutConfiguration, currentRow);
return field;
}

private FormFieldBase CreateFormField(TModel model, IValidator<TModel> validator)
{
var memberInfo = expression.GetMember();
var memberInfo = Expression.GetMember();
var getter = FormFieldAccessorCache.GetCachedGetter<TModel, TProperty>(memberInfo);
var setter = FormFieldAccessorCache.GetCachedSetter<TModel, TProperty>(memberInfo);

return (this) switch
{
{ controlTemplateName: FormFieldNames.CheckBox } => new CheckBoxFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.DatePicker } => new DatePickerFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.Editor } => new EditorFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.Entry } => new EntryFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.Slider } => new SliderFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.Stepper } => new StepperFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.Switch } => new SwitchFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ controlTemplateName: FormFieldNames.TimePicker } => new TimePickerFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
_ => new CustomTemplateFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, controlTemplateName, validator)
{ FormFieldTemplateName: FormFieldNames.CheckBox } => new CheckBoxFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.DatePicker } => new DatePickerFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.Editor } => new EditorFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.Entry } => new EntryFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.Slider } => new SliderFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.Stepper } => new StepperFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.Switch } => new SwitchFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
{ FormFieldTemplateName: FormFieldNames.TimePicker } => new TimePickerFormField<TModel, TProperty>(model, memberInfo.Name, getter, setter, validator),
_ => CreateCustomFormField(model, memberInfo.Name, getter, setter, validator)
};
}

public ICheckBoxFormFieldBuilder<TModel> AsCheckBox()
protected virtual FormFieldBase CreateCustomFormField(TModel model, string memberName, Func<TModel, TProperty> getter, Action<TModel, TProperty> setter, IValidator<TModel> validator = null)
{
controlTemplateName = FormFieldNames.CheckBox;
formFieldConfiguration = new CheckBoxFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

return this;
throw new ArgumentOutOfRangeException();
}

public ICustomTemplateFormFieldBuilder<TModel> AsCustomTemplate(string templateName)
public ICheckBoxFormFieldBuilder<TModel> AsCheckBox()
{
controlTemplateName = templateName;
formFieldConfiguration = new CustomTemplateFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.CheckBox;
FormFieldConfiguration = new CheckBoxFormFieldConfiguration();

return this;
}

public IDatePickerFormFieldBuilder<TModel> AsDatePicker()
{
controlTemplateName = FormFieldNames.DatePicker;
formFieldConfiguration = new DatePickerFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.DatePicker;
FormFieldConfiguration = new DatePickerFormFieldConfiguration();

return this;
}

public IEditorFormFieldBuilder<TModel> AsEditor()
{
controlTemplateName = FormFieldNames.Editor;
formFieldConfiguration = new EditorFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.Editor;
FormFieldConfiguration = new EditorFormFieldConfiguration();

return this;
}

public IEntryFormFieldBuilder<TModel> AsEntry()
{
controlTemplateName = FormFieldNames.Entry;
formFieldConfiguration = new EntryFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.Entry;
FormFieldConfiguration = new EntryFormFieldConfiguration();

return this;
}

public ISliderFormFieldBuilder<TModel> AsSlider()
{
controlTemplateName = FormFieldNames.Slider;
formFieldConfiguration = new SliderFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.Slider;
FormFieldConfiguration = new SliderFormFieldConfiguration();

return this;
}

public IStepperFormFieldBuilder<TModel> AsStepper()
{
controlTemplateName = FormFieldNames.Stepper;
formFieldConfiguration = new StepperFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.Stepper;
FormFieldConfiguration = new StepperFormFieldConfiguration();

return this;
}

public ISwitchFormFieldBuilder<TModel> AsSwitch()
{
controlTemplateName = FormFieldNames.Switch;
formFieldConfiguration = new SwitchFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.Switch;
FormFieldConfiguration = new SwitchFormFieldConfiguration();

return this;
}

public ITimePickerFormFieldBuilder<TModel> AsTimePicker()
{
controlTemplateName = FormFieldNames.TimePicker;
formFieldConfiguration = new TimePickerFormFieldConfiguration();
layoutConfiguration = new FormFieldLayoutConfiguration();

FormFieldTemplateName = FormFieldNames.TimePicker;
FormFieldConfiguration = new TimePickerFormFieldConfiguration();

return this;
}

public ICheckBoxFormFieldBuilder<TModel> WithConfiguration(Action<CheckBoxFormFieldConfiguration> configure)
{
configure?.Invoke((CheckBoxFormFieldConfiguration)formFieldConfiguration);
return this;
}

public ICustomTemplateFormFieldBuilder<TModel> WithConfiguration(Action<CustomTemplateFormFieldConfiguration> configure)
{
configure?.Invoke((CustomTemplateFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((CheckBoxFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public IDatePickerFormFieldBuilder<TModel> WithConfiguration(Action<DatePickerFormFieldConfiguration> configure)
{
configure?.Invoke((DatePickerFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((DatePickerFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public IEditorFormFieldBuilder<TModel> WithConfiguration(Action<EditorFormFieldConfiguration> configure)
{
configure?.Invoke((EditorFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((EditorFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public IEntryFormFieldBuilder<TModel> WithConfiguration(Action<EntryFormFieldConfiguration> configure)
{
configure?.Invoke((EntryFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((EntryFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public ISliderFormFieldBuilder<TModel> WithConfiguration(Action<SliderFormFieldConfiguration> configure)
{
configure?.Invoke((SliderFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((SliderFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public IStepperFormFieldBuilder<TModel> WithConfiguration(Action<StepperFormFieldConfiguration> configure)
{
configure?.Invoke((StepperFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((StepperFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public ISwitchFormFieldBuilder<TModel> WithConfiguration(Action<SwitchFormFieldConfiguration> configure)
{
configure?.Invoke((SwitchFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((SwitchFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public ITimePickerFormFieldBuilder<TModel> WithConfiguration(Action<TimePickerFormFieldConfiguration> configure)
{
configure?.Invoke((TimePickerFormFieldConfiguration)formFieldConfiguration);
configure?.Invoke((TimePickerFormFieldConfiguration)FormFieldConfiguration);
return this;
}

public ILayoutFieldBuilder WithLayout(Action<FormFieldLayoutConfiguration> configure)
{
configure?.Invoke(layoutConfiguration);
configure?.Invoke(LayoutConfiguration);
return this;
}
}
6 changes: 0 additions & 6 deletions Maui.FluentForms/Builders/IFormFieldBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace Maui.FluentForms.Builders;
public interface IFormFieldBuilder<TModel>
{
ICheckBoxFormFieldBuilder<TModel> AsCheckBox();
ICustomTemplateFormFieldBuilder<TModel> AsCustomTemplate(string templateName);
IDatePickerFormFieldBuilder<TModel> AsDatePicker();
IEditorFormFieldBuilder<TModel> AsEditor();
IEntryFormFieldBuilder<TModel> AsEntry();
Expand All @@ -28,11 +27,6 @@ public interface ICheckBoxFormFieldBuilder<TModel> : ILayoutFieldBuilder
ICheckBoxFormFieldBuilder<TModel> WithConfiguration(Action<CheckBoxFormFieldConfiguration> configure);
}

public interface ICustomTemplateFormFieldBuilder<TModel> : ILayoutFieldBuilder
{
ICustomTemplateFormFieldBuilder<TModel> WithConfiguration(Action<CustomTemplateFormFieldConfiguration> configure);
}

public interface IDatePickerFormFieldBuilder<TModel> : ILayoutFieldBuilder
{
IDatePickerFormFieldBuilder<TModel> WithConfiguration(Action<DatePickerFormFieldConfiguration> configure);
Expand Down

This file was deleted.

4 changes: 2 additions & 2 deletions Maui.FluentForms/Extensions/AppHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

public static class AppHostBuilderExtensions
{
public static MauiAppBuilder MapFormFieldContentControl<ContentView>(this MauiAppBuilder builder, string templateName)
public static MauiAppBuilder MapFormFieldContentControl<ContentView>(this MauiAppBuilder builder, string formFieldTemplateName)
{
FormFieldDataTemplateSelector.MapFormFieldContentControl<ContentView>(templateName);
FormFieldDataTemplateSelector.MapFormFieldContentControl<ContentView>(formFieldTemplateName);
return builder;
}
}
9 changes: 8 additions & 1 deletion Maui.FluentForms/FormBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ public IFormFieldBuilder<TModel> FieldFor<TProperty>(Expression<Func<TModel, TPr
{
_ = expression ?? throw new ArgumentNullException(nameof(expression));

var builder = new FormFieldBuilder<TModel, TProperty>(expression);
return FieldFor(new FormFieldBuilder<TModel, TProperty>(expression));
}

public TBuilder FieldFor<TBuilder>(TBuilder builder)
where TBuilder : IFormFieldBuilder<TModel>
{
_ = builder ?? throw new ArgumentNullException(nameof(builder));

builders.Add(builder);
return builder;
}
Expand Down
6 changes: 3 additions & 3 deletions Maui.FluentForms/FormFieldDataTemplateSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ public class FormFieldDataTemplateSelector : DataTemplateSelector
{
private static IDictionary<string, Type> mappings = new Dictionary<string, Type>();

internal static void MapFormFieldContentControl<ContentView>(string templateName)
internal static void MapFormFieldContentControl<ContentView>(string formFieldTemplateName)
{
mappings.Add(templateName, typeof(ContentView));
mappings.Add(formFieldTemplateName, typeof(ContentView));
}

protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
var contentControlType = mappings[((FormFieldBase)item).FieldTemplateName];
var contentControlType = mappings[((FormFieldBase)item).FormFieldTemplateName];
return new DataTemplate(contentControlType);
}
}
5 changes: 2 additions & 3 deletions Maui.FluentForms/FormFields/CheckBoxFormField.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

using Maui.FluentForms.Configuration;
using Maui.FluentForms.Configuration;
using Maui.FluentForms.Validation;

namespace Maui.FluentForms.FormFields;
Expand All @@ -11,7 +10,7 @@ public CheckBoxFormField(TModel model, string memberName, Func<TModel, TProperty
{
}

internal override void ApplyConfiguration(IFormFieldConfiguration configuration)
public override void ApplyConfiguration(IFormFieldConfiguration configuration)
{
// no-op
return;
Expand Down
17 changes: 0 additions & 17 deletions Maui.FluentForms/FormFields/CustomTemplateFormField.cs

This file was deleted.

2 changes: 1 addition & 1 deletion Maui.FluentForms/FormFields/DatePickerFormField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public DatePickerFormField(TModel model, string memberName, Func<TModel, TProper
{
}

internal override void ApplyConfiguration(IFormFieldConfiguration configuration)
public override void ApplyConfiguration(IFormFieldConfiguration configuration)
{
var typedConfiguration = (DatePickerFormFieldConfiguration)configuration;

Expand Down
2 changes: 1 addition & 1 deletion Maui.FluentForms/FormFields/EditorFormField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public EditorFormField(TModel model, string memberName, Func<TModel, TProperty>
{
}

internal override void ApplyConfiguration(IFormFieldConfiguration configuration)
public override void ApplyConfiguration(IFormFieldConfiguration configuration)
{
var typedConfig = (EditorFormFieldConfiguration)configuration;

Expand Down
2 changes: 1 addition & 1 deletion Maui.FluentForms/FormFields/EntryFormField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public EntryFormField(TModel model, string memberName, Func<TModel, TProperty> g
{
}

internal override void ApplyConfiguration(IFormFieldConfiguration configuration)
public override void ApplyConfiguration(IFormFieldConfiguration configuration)
{
var typedConfig = (EntryFormFieldConfiguration)configuration;

Expand Down
Loading

0 comments on commit 550339e

Please sign in to comment.