Skip to content

Commit 670d839

Browse files
committed
Started creation proper implementation (form, section (including nesting), navigation)
Co-habitation of html helper and tag helper syntax
1 parent 1440fdc commit 670d839

21 files changed

+520
-135
lines changed

ChameleonForms.Core/HtmlAttributes.cs

+34
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ public HtmlAttributes(IDictionary<string, object> attributes)
4646
Attrs(attributes);
4747
}
4848

49+
/// <summary>
50+
/// Constructs a <see cref="HtmlAttributes"/> object using a dictionary to express the attributes.
51+
/// </summary>
52+
/// <example>
53+
/// var h = new HtmlAttributes(new Dictionary&lt;string, string&gt; {{"style", "width: 100%;"}, {"cellpadding", "0"}, {"class", "class1 class2"}, {"src", "http://url/"}, {"data-somedata", "\"rubbi&amp;h\""}});
54+
/// </example>
55+
/// <param name="attributes">A dictionary of attributes</param>
56+
public HtmlAttributes(IDictionary<string, string> attributes)
57+
{
58+
Attrs(attributes);
59+
}
60+
4961
/// <summary>
5062
/// Constructs a <see cref="HtmlAttributes"/> object using an anonymous object to express the attributes.
5163
/// </summary>
@@ -180,6 +192,18 @@ public HtmlAttributes Attrs(IDictionary<string, object> attributes)
180192
return this;
181193
}
182194

195+
/// <summary>
196+
/// Adds or updates a set of HTML attributes using a dictionary to express the attributes.
197+
/// </summary>
198+
/// <param name="attributes">A dictionary of attributes</param>
199+
/// <returns>The <see cref="HtmlAttributes"/> attribute to allow for method chaining</returns>
200+
public HtmlAttributes Attrs(IDictionary<string, string> attributes)
201+
{
202+
_tagBuilder.MergeAttributes(attributes, true);
203+
204+
return this;
205+
}
206+
183207
/// <summary>
184208
/// Adds or updates a set of HTML attributes using anonymous objects to express the attributes.
185209
/// </summary>
@@ -204,6 +228,16 @@ public static implicit operator HtmlAttributes(Dictionary<string, object> attrib
204228
return new HtmlAttributes(attributes);
205229
}
206230

231+
/// <summary>
232+
/// Implicitly convert from a dictionary to a new <see cref="HtmlAttributes"/> object.
233+
/// </summary>
234+
/// <param name="attributes">The dictionary of HTML attributes</param>
235+
/// <returns>The new <see cref="HtmlAttributes"/> object</returns>
236+
public static implicit operator HtmlAttributes(Dictionary<string, string> attributes)
237+
{
238+
return new HtmlAttributes(attributes);
239+
}
240+
207241
/// <inheritdoc />
208242
public virtual void WriteTo(TextWriter writer, HtmlEncoder encoder)
209243
{

ChameleonForms.Example/ChameleonFormTagHelper.cs

-45
This file was deleted.

ChameleonForms.Example/FieldTagHelper.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq.Expressions;
44
using ChameleonForms.Component;
55
using ChameleonForms.Component.Config;
6+
using ChameleonForms.Utils;
67
using Microsoft.AspNetCore.Razor.TagHelpers;
78
using Microsoft.AspNetCore.Mvc.Rendering;
89
using Microsoft.AspNetCore.Mvc.ViewFeatures;
@@ -44,6 +45,8 @@ public class FieldTagHelper : TagHelper, IFieldConfigurableTagHelper
4445
[ViewContext]
4546
public ViewContext ViewContext { get; set; }
4647

48+
public IFieldConfigurableTagHelper Config { get; set; }
49+
4750

4851
public ModelExpression For { get; set; }
4952
public IFieldConfiguration Configuration { get; set; }
@@ -56,13 +59,11 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
5659

5760
public void ProcessInternal<TModel, TField>(TagHelperContext context, TagHelperOutput output, Expression<Func<TModel, TField>> @for)
5861
{
59-
var helper = ViewContext.HttpContext.RequestServices.GetRequiredService<IHtmlHelper<TModel>>();
60-
(helper as HtmlHelper<TModel>)?.Contextualize(ViewContext);
61-
var s = ViewContext.ViewData["ChameleonFormSection"] as Section<TModel>;
62-
var ff = ViewContext.ViewData["ChameleonFormField"] as Field<TModel>;
62+
var helper = ViewContext.GetHtmlHelper<TModel>();
6363

64-
if (s != null)
64+
if (helper.IsInChameleonFormsSection())
6565
{
66+
var s = helper.GetChameleonFormsSection();
6667
if (output.TagMode == TagMode.SelfClosing)
6768
{
6869
output.TagMode = TagMode.StartTagAndEndTag;
@@ -81,6 +82,7 @@ public void ProcessInternal<TModel, TField>(TagHelperContext context, TagHelperO
8182
}
8283
else
8384
{
85+
var ff = ViewContext.ViewData["ChameleonFormField"] as Field<TModel>;
8486
output.TagMode = TagMode.StartTagAndEndTag;
8587
output.TagName = null;
8688
output.Content.SetHtmlContent(ff.FieldFor(@for).Configure(this));

ChameleonForms.Example/PartialFormTagHelper.cs

+5-14
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
using System.Linq.Expressions;
33
using System.Text.Encodings.Web;
44
using ChameleonForms.Component;
5+
using ChameleonForms.Utils;
56
using JetBrains.Annotations;
67
using Microsoft.AspNetCore.Razor.TagHelpers;
78
using Microsoft.AspNetCore.Mvc.Rendering;
89
using Microsoft.AspNetCore.Mvc.ViewFeatures;
9-
using Microsoft.Extensions.DependencyInjection;
1010

1111
namespace ChameleonForms.Example
1212
{
@@ -31,32 +31,23 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
3131

3232
public void ProcessInternal<TModel, TPartialModel>(TagHelperContext context, TagHelperOutput output, Expression<Func<TModel, TPartialModel>> @for)
3333
{
34-
var helper = ViewContext.HttpContext.RequestServices.GetRequiredService<IHtmlHelper<TModel>>();
35-
(helper as HtmlHelper<TModel>)?.Contextualize(ViewContext);
36-
var f = ViewContext.ViewData["ChameleonForm"] as Form<TModel>;
37-
var s = ViewContext.ViewData["ChameleonFormSection"] as Section<TModel>;
38-
if (s != null)
34+
var helper = ViewContext.GetHtmlHelper<TModel>();
35+
if (helper.IsInChameleonFormsSection())
3936
{
37+
var s = helper.GetChameleonFormsSection();
4038
output.TagMode = TagMode.StartTagAndEndTag;
4139
output.TagName = null;
4240
output.Content.SetHtmlContent(s.PartialFor(@for, Name));
4341
}
4442
else
4543
{
44+
var f = helper.GetChameleonForm();
4645
output.TagMode = TagMode.StartTagAndEndTag;
4746
output.TagName = null;
4847
output.Content.SetHtmlContent(f.PartialFor(@for, Name));
4948
}
5049
}
5150

52-
private void OutputSection<TModel>(TagHelperOutput output, IHtmlHelper<TModel> helper, Section<TModel> s)
53-
{
54-
helper.ViewData["ChameleonFormSection"] = s;
55-
output.GetChildContentAsync().GetAwaiter().GetResult()
56-
.WriteTo(helper.ViewContext.Writer, HtmlEncoder.Default);
57-
ViewContext.ViewData.Remove("ChameleonFormSection");
58-
}
59-
6051
static Expression GetPropertySelector(Type modelType, string propertyName)
6152
{
6253
var arg = Expression.Parameter(modelType, "x");

ChameleonForms.Example/SectionTagHelper.cs

-61
This file was deleted.

ChameleonForms.Example/Views/Home/Index.cshtml

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,47 @@
1-
@model ViewModelExample
1+
@using ChameleonForms.Utils
2+
@model ViewModelExample
23

34
@{
45
ViewBag.Title = "ChameleonForms";
56
Func<dynamic, IHtmlContent> x = @<strong>Supppp</strong>;
67
}
78

8-
<chameleon-form enctype="EncType.UrlEncoded" action="@Url.Action("Index")" method="Post">
9-
<section heading="Wassup" leading-html="x">
9+
<chameleon-form>
10+
<form-section heading="Wassup" leading-html="x">
1011
<p>Yo</p>
1112
<field for="Decimal" add-class="asdf asf ew" label="awefawefEWAF #$%&" attr-data-test="wassup" />
1213
<field for="Int">
1314
<field for="NullableInt" />
1415
</field>
16+
<form-section heading-html="x">
17+
<field for="TextAreaField" />
18+
</form-section>
1519
<partial name="_Child" />
1620
<partial-form name="_Child2" for="Child" />
17-
</section>
21+
</form-section>
1822
<partial-form name="_Child2" for="Child" />
23+
@* Mix and match helper syntax with tag helpers and vice versa *@
24+
@Html.GetChameleonForm().FieldElementFor(m => m.ListId)
25+
@using (var s = Html.GetChameleonForm().BeginSection("Section from helper syntax"))
26+
{
27+
@s.FieldFor(m => m.SomeEnum)
28+
<field for="Boolean" />
29+
}
30+
<form-navigation>
31+
@{ var n = Html.GetChameleonFormsNavigation();}
32+
@n.Submit("asdf")
33+
@n.Reset("Reset")
34+
</form-navigation>
1935
</chameleon-form>
2036

37+
38+
@* Not possible - compile error, model has to be the page model with tag helpers
39+
<chameleon-form enctype="EncType.UrlEncoded" action="@Url.Action("ChameleonForms", "Comparison")" method="Post" model="new SignupViewModel()">
40+
<section heading="asdf">
41+
<field for="FirstName" />
42+
</section>
43+
</chameleon-form>*@
44+
2145
<partial name="_OtherForm" model="new ComparisonController.SignupViewModel()" />
2246

2347
<h1>ChameleonForms</h1>
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@model ComparisonController.SignupViewModel
22

3-
<chameleon-form action="@Url.Action("ChameleonForms", "Comparison")">
4-
<section heading="asdf">
5-
<field for="FirstName"></field>
6-
</section>
3+
<chameleon-form action="@Url.Action("ChameleonForms", "Comparison")" method="Post" enctype="UrlEncoded">
4+
<form-section heading="asdf">
5+
<field for="FirstName" />
6+
</form-section>
77
</chameleon-form>

ChameleonForms.Example/Views/_ViewImports.cshtml

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
@using Microsoft.AspNetCore.Mvc.Rendering
1010

1111
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
12+
@addTagHelper ChameleonForms.TagHelpers.*, ChameleonForms
1213
@addTagHelper *, ChameleonForms.Example

ChameleonForms.sln.DotSettings

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66
<s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=Jasmine/@EntryIndexedValue">True</s:Boolean>
77
<s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=QUnit/@EntryIndexedValue">True</s:Boolean>
88
<s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue">&lt;data&gt;&lt;IncludeFilters /&gt;&lt;ExcludeFilters /&gt;&lt;/data&gt;</s:String>
9-
<s:String x:Key="/Default/FilterSettingsManager/AttributeFilterXml/@EntryValue">&lt;data /&gt;</s:String></wpf:ResourceDictionary>
9+
<s:String x:Key="/Default/FilterSettingsManager/AttributeFilterXml/@EntryValue">&lt;data /&gt;</s:String>
10+
<s:Boolean x:Key="/Default/UserDictionary/Words/=contextualise/@EntryIndexedValue">True</s:Boolean>
11+
<s:Boolean x:Key="/Default/UserDictionary/Words/=contextualised/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

ChameleonForms/Component/FormComponent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public void WriteTo(TextWriter writer, HtmlEncoder encoder)
7575
}
7676

7777
/// <inheritdoc />
78-
public void Dispose()
78+
public virtual void Dispose()
7979
{
8080
if (!IsSelfClosing)
8181
Form.Write(End());

ChameleonForms/Component/Navigation.cs

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public class Navigation<TModel> : FormComponent<TModel>
1717
/// <param name="form">The form the message is being created in</param>
1818
public Navigation(IForm<TModel> form) : base(form, false)
1919
{
20+
form.HtmlHelper.ViewData[Constants.ViewDataNavigationKey] = this;
2021
Initialise();
2122
}
2223

@@ -160,6 +161,12 @@ public ButtonHtmlAttributes Reset(Func<dynamic, IHtmlContent> content)
160161
{
161162
return Reset(content(null));
162163
}
164+
165+
public override void Dispose()
166+
{
167+
base.Dispose();
168+
Form.HtmlHelper.ViewData.Remove(Constants.ViewDataNavigationKey);
169+
}
163170
}
164171

165172
/// <summary>

0 commit comments

Comments
 (0)