Skip to content
This repository has been archived by the owner on Jan 11, 2018. It is now read-only.

Commit

Permalink
Select now tracks the model value (if any) so that initial and subsiq…
Browse files Browse the repository at this point in the history
…uent AddOptions calls will automatically select the option if it matches the value - resolves #31
  • Loading branch information
daveaglick committed May 26, 2015
1 parent 9ec3553 commit 0c3de37
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 27 deletions.
42 changes: 32 additions & 10 deletions FluentBootstrap.Mvc/Forms/MvcFormExtensions.cs
Expand Up @@ -298,9 +298,15 @@ public static ValidationSummary<TModel> IncludePropertyErrors<TModel>(this Valid
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, helper.GetConfig().HtmlHelper.ViewData);
string expressionText = ExpressionHelper.GetExpressionText(expression);
string name = GetControlName(helper, expressionText);
string label = GetControlLabel(metadata, expressionText);
return helper.Select(name, label, options);
string name = GetControlName(helper, expressionText);
string label = GetControlLabel(metadata, expressionText);
ComponentBuilder<MvcBootstrapConfig<TModel>, Select> builder = helper.Select(name, label);
if (metadata.Model != null && !string.IsNullOrEmpty(name))
{
// Add the model value before adding options so they'll get selected on a match
builder.GetComponent().ModelValue = metadata.Model.ToString();
}
return builder.AddOptions(options);
}

public static ComponentBuilder<MvcBootstrapConfig<TModel>, Select> SelectFor<TComponent, TModel, TValue>(
Expand All @@ -310,8 +316,14 @@ public static ValidationSummary<TModel> IncludePropertyErrors<TModel>(this Valid
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, helper.GetConfig().HtmlHelper.ViewData);
string expressionText = ExpressionHelper.GetExpressionText(expression);
string name = GetControlName(helper, expressionText);
string label = GetControlLabel(metadata, expressionText);
return helper.Select(name, label, options);
string label = GetControlLabel(metadata, expressionText);
ComponentBuilder<MvcBootstrapConfig<TModel>, Select> builder = helper.Select(name, label);
if (metadata.Model != null && !string.IsNullOrEmpty(name))
{
// Add the model value before adding options so they'll get selected on a match
builder.GetComponent().ModelValue = metadata.Model.ToString();
}
return builder.AddOptions(options);
}

public static ComponentBuilder<MvcBootstrapConfig<TModel>, Select> SelectFor<TComponent, TModel, TValue>(
Expand All @@ -320,9 +332,15 @@ public static ValidationSummary<TModel> IncludePropertyErrors<TModel>(this Valid
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, helper.GetConfig().HtmlHelper.ViewData);
string expressionText = ExpressionHelper.GetExpressionText(expression);
string name = GetControlName(helper, expressionText);
string label = GetControlLabel(metadata, expressionText);
return helper.Select(name, label, selectList);
string name = GetControlName(helper, expressionText);
string label = GetControlLabel(metadata, expressionText);
ComponentBuilder<MvcBootstrapConfig<TModel>, Select> builder = helper.Select(name, label);
if (metadata.Model != null && !string.IsNullOrEmpty(name))
{
// Add the model value before adding options so they'll get selected on a match
builder.GetComponent().ModelValue = metadata.Model.ToString();
}
return builder.AddOptions(selectList);
}

public static ComponentBuilder<MvcBootstrapConfig<TModel>, Select> Select<TComponent, TModel>(
Expand All @@ -336,9 +354,13 @@ public static ValidationSummary<TModel> IncludePropertyErrors<TModel>(this Valid
public static ComponentBuilder<MvcBootstrapConfig<TModel>, Select> AddOptions<TModel>(
this ComponentBuilder<MvcBootstrapConfig<TModel>, Select> builder, IEnumerable<SelectListItem> selectList)
{
foreach (SelectListItem item in selectList)
if (selectList != null)
{
builder.AddChild(x => x.SelectOption(item.Text, item.Value, item.Selected));
foreach (SelectListItem item in selectList)
{
var item1 = item; // Avoid foreach variable access in closure
builder.AddChild(x => x.SelectOption(item1.Text, item1.Value, item1.Selected));
}
}
return builder;
}
Expand Down
3 changes: 2 additions & 1 deletion FluentBootstrap.Tests.Web/Controllers/MvcTestsController.cs
Expand Up @@ -15,7 +15,8 @@ public virtual ActionResult MvcTests(string view)
{
PropA = "A",
PropB = 2,
PropC = new Dictionary<int, string>()
PropC = "Two",
PropCOptions = new Dictionary<int, string>()
{
{ 1, "One"},
{ 2, "Two"},
Expand Down
3 changes: 2 additions & 1 deletion FluentBootstrap.Tests.Web/Models/MvcTests/ViewModel.cs
Expand Up @@ -11,7 +11,8 @@ public class ViewModel
[Display(Name = "Property A")]
public string PropA { get; set; }
public int PropB { get; set; }
public Dictionary<int, string> PropC { get; set; }
public string PropC { get; set; }
public Dictionary<int, string> PropCOptions { get; set; }
public bool PropD { get; set; }
}
}
17 changes: 14 additions & 3 deletions FluentBootstrap.Tests.Web/Views/MvcTests/MvcForms.cshtml
Expand Up @@ -57,7 +57,7 @@
{
using (var form = Html.Bootstrap().Form().HideValidationSummary().Begin())
{
@form.DisplayListFor(x => x.PropC.Values)
@form.DisplayListFor(x => x.PropCOptions.Values)
}
}

Expand All @@ -68,7 +68,7 @@
{
using (var form = Html.Bootstrap().Form().HideValidationSummary().Begin())
{
@form.EditorListFor(x => x.PropC.Values)
@form.EditorListFor(x => x.PropCOptions.Values)
}
}

Expand Down Expand Up @@ -125,7 +125,18 @@
{
using (var form = Html.Bootstrap().Form().HideValidationSummary().Begin())
{
@form.SelectFor(x => x.PropC, Model.PropC.Select(y => new KeyValuePair<string, string>(y.Key.ToString(), y.Value)))
@form.SelectFor(x => x.PropC, Model.PropCOptions.Select(y => new KeyValuePair<string, string>(y.Key.ToString(), y.Value)))
}
}

<hr />

@Html.Bootstrap().Heading1("Select For With Add Options")
using (Html.Bootstrap().Div().SetId("test-select-for-with-add-options").Begin())
{
using (var form = Html.Bootstrap().Form().HideValidationSummary().Begin())
{
@form.SelectFor(x => x.PropC).AddOptions(Model.PropCOptions.Select(y => new KeyValuePair<string, string>(y.Key.ToString(), y.Value)))
}
}
}
35 changes: 26 additions & 9 deletions FluentBootstrap.Tests/MvcFormsFixture.cs
Expand Up @@ -66,20 +66,20 @@ public void EditorOrDisplayForProducesCorrectHtml()
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-display-list-for",
@"<form role=""form"" method=""post"">
<div class=""form-group"">
<label for=""PropC_Values"" class=""control-label"">Values</label>
<div class=""form-control-static""><input id=""PropC_Values"" name=""PropC.Values"" type=""hidden"" value=""""><partial></partial>
<label for=""PropCOptions_Values"" class=""control-label"">Values</label>
<div class=""form-control-static""><input id=""PropCOptions_Values"" name=""PropCOptions.Values"" type=""hidden"" value=""""><partial></partial>
</div>
</div>
</form>");
}

[Test]
public void DisplayListForForProducesCorrectHtml()
public void DisplayListForProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-editor-list-for",
@"<form role=""form"" method=""post"">
<div class=""form-group"">
<label for=""PropC_Values"" class=""control-label"">Values</label>
<label for=""PropCOptions_Values"" class=""control-label"">Values</label>
<div><partial></partial>
</div>
</div>
Expand All @@ -90,7 +90,7 @@ public void DisplayListForForProducesCorrectHtml()
// So that part of the HTML has been removed for now - these will have to be verified manually

[Test]
public void InputForForProducesCorrectHtml()
public void InputForProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-input-for",
@"<form role=""form"" method=""post"">
Expand All @@ -102,7 +102,7 @@ public void InputForForProducesCorrectHtml()
}

[Test]
public void PasswordForForProducesCorrectHtml()
public void PasswordForProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-password-for",
@"<form role=""form"" method=""post"">
Expand All @@ -114,7 +114,7 @@ public void PasswordForForProducesCorrectHtml()
}

[Test]
public void CheckBoxForForProducesCorrectHtml()
public void CheckBoxForProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-checkbox-for",
@"<form role=""form"" method=""post"">
Expand All @@ -130,7 +130,7 @@ public void CheckBoxForForProducesCorrectHtml()
}

[Test]
public void RadioForForProducesCorrectHtml()
public void RadioForProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-radio-for",
@"<form role=""form"" method=""post"">
Expand Down Expand Up @@ -160,9 +160,26 @@ public void RadioForForProducesCorrectHtml()

// HtmlAgilityPack strips the closing </option> tag - very annoying!!
[Test]
public void SelectForForProducesCorrectHtml()
public void SelectForProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-select-for",
@"<form role=""form"" method=""post"">
<div class=""form-group"">
<label for=""PropC"" class=""control-label"">PropC</label>
<select name=""PropC"" id=""PropC"" class=""form-control"">
<option value=""One"">1
<option value=""Two"">2
<option value=""Three"">3
</select>
</div>
</form>");
}

// HtmlAgilityPack strips the closing </option> tag - very annoying!!
[Test]
public void SelectForWithAddOptionsProducesCorrectHtml()
{
TestHelper.AssertMvcHtml<ASP._Views_MvcTests_MvcForms_cshtml>("test-select-for-with-add-options",
@"<form role=""form"" method=""post"">
<div class=""form-group"">
<label for=""PropC"" class=""control-label"">PropC</label>
Expand Down
3 changes: 2 additions & 1 deletion FluentBootstrap.Tests/TestHelper.cs
Expand Up @@ -75,7 +75,8 @@ public static void AssertMvcHtml<TView>(string containerId, string expected, boo
{
PropA = "A",
PropB = 2,
PropC = new Dictionary<int, string>()
PropC = "Two",
PropCOptions = new Dictionary<int, string>()
{
{ 1, "One"},
{ 2, "Two"},
Expand Down
7 changes: 5 additions & 2 deletions FluentBootstrap/Forms/FormExtensions.cs
Expand Up @@ -315,7 +315,8 @@ public static class FormExtensions
{
foreach (string option in options)
{
builder.AddChild(x => x.SelectOption(option));
var option1 = option; // Avoid foreach variable access in closure
builder.AddChild(x => x.SelectOption(option1));
}
return builder;
}
Expand All @@ -325,7 +326,9 @@ public static class FormExtensions
{
foreach (KeyValuePair<string, string> option in options)
{
builder.AddChild(x => x.SelectOption(option.Key, option.Value));
var option1 = option; // Avoid foreach variable access in closure
builder.AddChild(x => x.SelectOption(option1.Key, option1.Value,
builder.Component.ModelValue != null && string.Equals(builder.Component.ModelValue, option1.Value, StringComparison.OrdinalIgnoreCase)));
}
return builder;
}
Expand Down
3 changes: 3 additions & 0 deletions FluentBootstrap/Forms/Select.cs
Expand Up @@ -13,6 +13,9 @@ public class Select : FormControl, IHasNameAttribute,
{
public bool Multiple { get; set; }

// This is needed so that when adding options, we can check if they match the model value and select if so
public string ModelValue { get; set; }

internal Select(BootstrapHelper helper)
: base(helper, "select", Css.FormControl)
{
Expand Down

0 comments on commit 0c3de37

Please sign in to comment.