Skip to content

Commit a03cbfa

Browse files
committed
Finished homepage
1 parent 7f9282d commit a03cbfa

File tree

5 files changed

+321
-6
lines changed

5 files changed

+321
-6
lines changed

docs/index.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,9 @@ ChameleonForms takes away the pain and repetition of building forms with ASP.NET
1313

1414
It's ideally suited for situations where you want to **quickly** build forms that are highly consistent and maintainable. If you are trying to build highly specialised forms that are individually, painstakingly crafted then that's not what this library is for. That's where it makes sense to break out your JavaScript library of choice.
1515

16-
Here's a quick example of what ChameleonForms looks like compared to a traditional ASP.NET MVC approach:
17-
18-
![Example of the code and display of a Chameleon-powered Bootstrap form compared to traditional approach](bootstrap-example-banner.png)
19-
2016
## Contents
2117

22-
* [Example](#example)
18+
* [Example in detail](#example)
2319
* [View model class](#view-model-class)
2420
* [Razor view](#razor-view)
2521
* [Rendered result](#rendered-result)

docs/signup-example-render.png

91.8 KB
Loading

docs/templates/chameleonforms/partials/home.tmpl.partial

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
<div class="clearfix"></div>
1212
<div class="lead-title">Shape-shifting your forms experience in ASP.NET Core.</div>
1313
<div class="sub-lead-title">ChameleonForms makes building consistent, correct forms that work well client-side and server-side easy and quick by using model-driven defaults, conventions, templates and terse, declarative, type-safe syntax.</div>
14-
<a class="lead-btn" href="docs/">Dive in</a>
14+
<a class="lead-btn" href="docs/getting-started.html">Dive in</a>
1515
</div>
1616
</div>

docs/templates/chameleonforms/styles/main.css

+17
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,20 @@
149149
margin-top: 50px;
150150
}
151151
}
152+
153+
pre {
154+
background: #FDFDFD;
155+
}
156+
157+
.hljs-string {
158+
color: #d14;
159+
}
160+
161+
.home-buttons .btn {
162+
background: #008800;
163+
border: 0;
164+
}
165+
166+
.home-buttons .btn:hover, .home-buttons .btn:active {
167+
background: #004700;
168+
}

index.md

+302
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,313 @@ Here are the things that ChameleonForms has done for us based on the model:
7373

7474
Other model-driven form features you can explore:
7575

76+
* [Getting started](docs/getting-started.md)
7677
* Inference from model type to output [Boolean fields](docs/boolean.md), [DateTime fields](docs/datetime.md), [Enum fields](docs/enum.md), [List fields](docs/list.md), [File upload fields](docs/file-upload.md) and [Number fields](docs/number.md)
7778
* Multiple-select: [Flags enum fields](docs/flags-enum.md), [Multiple-select enum fields](docs/multiple-enum.md) and [Multiple-select list fields](docs/multiple-list.md)
7879
* Inference from model property attributes to output [Textarea fields](docs/textarea.md), [Password fields](docs/password.md), [Email fields](docs/email.md) and [Uri fields](docs/uri.md) as well as supporting controlling the client-side and server-side validation of [DateTime fields](docs/datetime.md)
80+
* Client-side and server-side validation is given to us from the model metadata based on the [built-in ASP.NET Core MVC features](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-3.1).
81+
* The HTML that is rendered will always bind correctly to the view model on the ASP.NET Core MVC controller using the [built-in model binding](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-3.1).
7982

8083
***
8184

8285
</div>
8386
</div>
87+
88+
<p>&nbsp;</p>
89+
<p>&nbsp;</p>
90+
91+
92+
<div class="row">
93+
<div class="col-md-4">
94+
<h2>Rapid, consistent, correct forms</h2>
95+
<p>Use terse, declarative, type-safe, intellisense-friendly syntax to quickly define your forms and let conventions and templates take care of the detail so you don't have to.</p>
96+
<p>Your forms will be quicker to write and easier to maintain and you won't get stuck writing the same form boilerplate markup form after form after form. Plus, you can build in accessibility and consistency as cross-cutting concerns.</p>
97+
<p><strong>ChameleonForms really shines when you need to build a lot of forms quickly and consistently.</strong></p>
98+
</div>
99+
<div class="col-md-8">
100+
101+
102+
# [View (TH)](#tab/rapid-1)
103+
104+
**Tag helpers variant**
105+
106+
```cshtml
107+
@model SignupViewModel
108+
<h1>Account signup</h1>
109+
<chameleon-form attr-id="signup-form">
110+
<form-message type="Information" heading="Signup for an account">
111+
<message-paragraph>Please fill in your information below to signup for an account.</message-paragraph>
112+
</form-message>
113+
114+
<form-section heading="Your details">
115+
<field for="FirstName" />
116+
<field for="LastName" />
117+
<field for="DateOfBirth" hint="DD/MM/YYYY" />
118+
</form-section>
119+
120+
<form-section heading="Account details">
121+
<field for="EmailAddress" hint="An email will be sent to this address to confirm you own it" />
122+
<field for="Password" />
123+
<field for="MembershipType" />
124+
</form-section>
125+
126+
<form-section heading="Additional details">
127+
<field for="Bio" />
128+
<field for="Homepage" placeholder="https://" />
129+
</form-section>
130+
131+
<form-message type="Action" heading="Confirm the Terms & Conditions">
132+
<message-paragraph>Please <a href="#">read the terms and conditions</a></message-paragraph>
133+
<field-element for="TermsAndConditions" inline-label="I agree to the terms and conditions" />
134+
</form-message>
135+
136+
<form-navigation>
137+
<submit-button label="Signup" emphasis-style="Primary" />
138+
</form-navigation>
139+
</chameleon-form>
140+
```
141+
142+
# [View (HH)](#tab/rapid-2)
143+
144+
**HTML helpers variant**
145+
146+
```cshtml
147+
@model SignupViewModel
148+
<h1>Account signup</h1>
149+
@using (var f = Html.BeginChameleonForm(htmlAttributes: Html.Attrs().Id("signup-form")))
150+
{
151+
using (var m = f.BeginMessage(MessageType.Information, "Signup for an account"))
152+
{
153+
@m.Paragraph("Please fill in your information below to signup for an account.")
154+
}
155+
156+
using (var s = f.BeginSection("Your details"))
157+
{
158+
@s.FieldFor(m => m.FirstName)
159+
@s.FieldFor(m => m.LastName)
160+
@s.FieldFor(m => m.DateOfBirth).WithHint("DD/MM/YYYY")
161+
}
162+
163+
using (var s = f.BeginSection("Account details"))
164+
{
165+
@s.FieldFor(m => m.EmailAddress).WithHint("An email will be sent to this address to confirm you own it")
166+
@s.FieldFor(m => m.Password)
167+
@s.FieldFor(m => m.MembershipType)
168+
}
169+
170+
using (var s = f.BeginSection("Additional details"))
171+
{
172+
@s.FieldFor(m => m.Bio).Rows(2).Cols(60)
173+
@s.FieldFor(m => m.Homepage).Placeholder("https://")
174+
}
175+
176+
using (var m = f.BeginMessage(MessageType.Action, "Confirm the Terms & Conditions"))
177+
{
178+
@m.Paragraph(@<text>Please <a href="/terms">read the terms and conditions</a></text>)
179+
@f.FieldElementFor(mm => mm.TermsAndConditions).InlineLabel("I agree to the terms and conditions")
180+
}
181+
182+
using (var n = f.BeginNavigation())
183+
{
184+
@n.Submit("Signup").WithStyle(EmphasisStyle.Primary)
185+
}
186+
}
187+
```
188+
189+
# [Visual result](#tab/rapid-3)
190+
191+
![Screenshot of the rendered form](docs/signup-example-render.png)
192+
193+
# [HTML output](#tab/rapid-4)
194+
```html
195+
<h1>Account signup</h1>
196+
<form action="" enctype="application/x-www-form-urlencoded" id="signup-form" method="post" novalidate="novalidate">
197+
<div class="panel panel-info">
198+
<div class="panel-heading">
199+
<h4 class="panel-title">Signup for an account</h4>
200+
</div>
201+
<div class="panel-body">
202+
<p>
203+
Please fill in your information below to signup for an account.
204+
</p>
205+
</div>
206+
</div>
207+
<fieldset>
208+
<legend>Your details</legend>
209+
<div class="form-group">
210+
<label class="control-label" for="FirstName">First name</label>
211+
<div class="input-group">
212+
<input class="form-control" data-val="true" data-val-required="The First name field is required." id="FirstName" name="FirstName" required="required" type="text" value="" />
213+
<div class="input-group-addon required">
214+
<em class="required" title="Required">&lowast;</em>
215+
</div>
216+
</div>
217+
<span class="field-validation-valid help-block" data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
218+
</div>
219+
<div class="form-group">
220+
<label class="control-label" for="LastName">Last name</label>
221+
<div class="input-group">
222+
<input class="form-control" data-val="true" data-val-required="The Last name field is required." id="LastName" name="LastName" required="required" type="text" value="" />
223+
<div class="input-group-addon required">
224+
<em class="required" title="Required">&lowast;</em>
225+
</div>
226+
</div>
227+
<span class="field-validation-valid help-block" data-valmsg-for="LastName" data-valmsg-replace="true"></span>
228+
</div>
229+
<div class="form-group">
230+
<label class="control-label" for="DateOfBirth">Date of birth</label>
231+
<div class="input-group">
232+
<input aria-describedby="DateOfBirth--Hint" class="form-control" data-val="true" data-val-date="The field Date of birth must be a date with format d/M/yyyy." data-val-format="d/M/yyyy" data-val-required="The Date of birth field is required." id="DateOfBirth" name="DateOfBirth" required="required" type="text" value="" />
233+
<div class="input-group-addon required">
234+
<em class="required" title="Required">&lowast;</em>
235+
</div>
236+
</div>
237+
<div class="help-block form-hint" id="DateOfBirth--Hint">DD/MM/YYYY</div>
238+
<span class="field-validation-valid help-block" data-valmsg-for="DateOfBirth" data-valmsg-replace="true"></span>
239+
</div>
240+
</fieldset>
241+
<fieldset>
242+
<legend>Account details</legend>
243+
<div class="form-group">
244+
<label class="control-label" for="EmailAddress">Email address</label>
245+
<div class="input-group">
246+
<input aria-describedby="EmailAddress--Hint" class="form-control" data-val="true" data-val-email="The Email address field is not a valid e-mail address." data-val-required="The Email address field is required." id="EmailAddress" name="EmailAddress" required="required" type="email" value="" />
247+
<div class="input-group-addon required">
248+
<em class="required" title="Required">&lowast;</em>
249+
</div>
250+
</div>
251+
<div class="help-block form-hint" id="EmailAddress--Hint">An email will be sent to this address to confirm you own it</div>
252+
<span class="field-validation-valid help-block" data-valmsg-for="EmailAddress" data-valmsg-replace="true"></span>
253+
</div>
254+
<div class="form-group">
255+
<label class="control-label" for="Password">Password</label>
256+
<div class="input-group">
257+
<input class="form-control" data-val="true" data-val-required="The Password field is required." id="Password" name="Password" required="required" type="password" />
258+
<div class="input-group-addon required">
259+
<em class="required" title="Required">&lowast;</em>
260+
</div>
261+
</div>
262+
<span class="field-validation-valid help-block" data-valmsg-for="Password" data-valmsg-replace="true"></span>
263+
</div>
264+
<div class="form-group">
265+
<label class="control-label" for="MembershipType">Membership type</label>
266+
<div class="input-group">
267+
<select class="form-control" data-val="true" data-val-required="The Membership type field is required." id="MembershipType" name="MembershipType" required="required">
268+
<option selected="selected" value="Standard">Standard</option>
269+
<option value="Bonze">Bonze</option>
270+
<option value="Silver">Silver</option>
271+
<option value="Gold">Gold</option>
272+
<option value="Platinum">Platinum</option>
273+
</select>
274+
<div class="input-group-addon required">
275+
<em class="required" title="Required">&lowast;</em>
276+
</div>
277+
</div>
278+
<span class="field-validation-valid help-block" data-valmsg-for="MembershipType" data-valmsg-replace="true"></span>
279+
</div>
280+
</fieldset>
281+
<fieldset>
282+
<legend>Additional details</legend>
283+
<div class="form-group">
284+
<label class="control-label" for="Bio">Bio</label>
285+
<textarea class="form-control" cols="20" id="Bio" name="Bio" rows="2"></textarea>
286+
<span class="field-validation-valid help-block" data-valmsg-for="Bio" data-valmsg-replace="true"></span>
287+
</div>
288+
<div class="form-group">
289+
<label class="control-label" for="Homepage">Homepage</label>
290+
<input class="form-control" id="Homepage" name="Homepage" placeholder="http://" type="url" value="" />
291+
<span class="field-validation-valid help-block" data-valmsg-for="Homepage" data-valmsg-replace="true"></span>
292+
</div>
293+
</fieldset>
294+
<div class="panel panel-primary">
295+
<div class="panel-heading">
296+
<h4 class="panel-title">Confirm the Terms &amp; Conditions</h4>
297+
</div>
298+
<div class="panel-body">
299+
<p>
300+
Please
301+
<a href="#">read the terms and conditions</a>
302+
</p>
303+
<input data-val="true" data-val-required="The Terms and conditions field is required." id="TermsAndConditions" name="TermsAndConditions" required="required" type="checkbox" value="true" />
304+
<label for="TermsAndConditions">I agree to the terms and conditions</label>
305+
</div>
306+
</div>
307+
<div class="btn-group">
308+
<button class="btn btn-primary" type="submit">Signup</button>
309+
</div>
310+
</form>
311+
```
312+
313+
# [Startup / VM](#tab/rapid-5)
314+
**Startup**
315+
```c#
316+
public void ConfigureServices(IServiceCollection services)
317+
{
318+
...
319+
services.AddChameleonForms<TwitterBootstrap3FormTemplate>();
320+
}
321+
```
322+
323+
**View model**
324+
```c#
325+
public class SignupViewModel
326+
{
327+
[Required]
328+
public string FirstName { get; set; }
329+
[Required]
330+
public string LastName { get; set; }
331+
[DisplayFormat(DataFormatString = "{0:d/M/yyyy}", ApplyFormatInEditMode = true)]
332+
public DateTime DateOfBirth { get; set; }
333+
334+
[Required]
335+
[EmailAddress]
336+
public string EmailAddress { get; set; }
337+
[Required]
338+
[DataType(DataType.Password)]
339+
public string Password { get; set; }
340+
public MembershipType MembershipType { get; set; }
341+
342+
[Url]
343+
public Uri Homepage { get; set; }
344+
[DataType(DataType.MultilineText)]
345+
public string Bio { get; set; }
346+
347+
[Required]
348+
public bool TermsAndConditions { get; set; }
349+
}
350+
public enum MembershipType
351+
{
352+
Standard,
353+
Bonze,
354+
Silver,
355+
Gold,
356+
Platinum
357+
}
358+
```
359+
360+
# [Notes](#tab/rapid-6)
361+
362+
Here are the things that ChameleonForms has done for us:
363+
364+
* We've been able to declaratively declare the structure of the form rather than the presentation of the form - this is akin to the separation we get from declarative HTML separated from CSS and JS.
365+
* The resulting markup for the form itself, the user messages, form sections, fields and navigation have all been sorted out, consistently, for us using a form template we've been able to select in `Startup.cs` (in this case using Bootstrap). The amount of HTML that is required to render that form (see HTML output tab) is a lot - it's easy to parts of that wrong if you need to specify the boilerplate manually, plus it then couples all of your forms to that specific template. With ChameleonForms we can swap out the template with a single line of code, for instance when you want to switch from Bootstrap to a more customised setup if you make it big and want to add some bespoke design love.
366+
* All of the syntax is type-safe and thus benefits from a combination of intellisense to speed up writing and protection from runtime mistakes (e.g. id mismatches etc.). We also know that the form will definitely correctly bind to the view model on the server-side MVC controller without needing to perform slow UI or manual tests.
367+
* All fields automatically have a combination of server-side validation and client-side validation logic and messages added in for us built on top of the ASP.NET Core MVC features.
368+
* All fields are easily and tersely configurable to include hints and other tweaks to the rendered markup using typesafe / intellisense code.
369+
370+
Documentation worth exploring to dive into more detail includes:
371+
372+
* [Deep-dive on the example](docs/index.md)
373+
* [Configuring ChameleonForms](docs/configuration.md)
374+
* [Bootstrap template](docs/bootstrap-template.md)
375+
* [Field Configuration](docs/field-configuration.md)
376+
* [Form structure](docs/getting-started.md#how-are-chameleonforms-forms-structured): [Form](docs/the-form.md), [Message](docs/the-message.md), [Section](docs/the-section.md), [Navigation](docs/the-navigation.md), [Field](docs/field.md), [Field Element](docs/field-element.md), [Field Label](docs/field-label.md) and [Field Validation HTML](docs/field-validation-html.md)
377+
* [Using different form templates](docs/form-templates.md) and [creating custom form templates](docs/custom-template.md)
378+
379+
***
380+
381+
</div>
382+
</div>
383+
384+
<p>&nbsp;</p>
385+
<p class="home-buttons"><a href="docs/index.md" class="btn btn-primary btn-lg">Tell me more?!</a> <a href="docs/getting-started.md" class="btn btn-primary btn-lg">I want to get started!</a></p>

0 commit comments

Comments
 (0)