Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Creating the AureliaBindTagHelper to render Aurelia bindings for ASP.…
…NET MVC model members
- Loading branch information
Showing
2 changed files
with
148 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc.ViewFeatures; | ||
using Microsoft.AspNetCore.Razor.TagHelpers; | ||
|
||
namespace FooBar.Web.TagHelpers | ||
{ | ||
[HtmlTargetElement(Attributes = VkAuBindPrefix + "*")] | ||
public class AureliaBindTagHelper : TagHelper | ||
{ | ||
private const string VkAuBindPrefix = "th-au-bind-"; | ||
private const string VkAuValueConvertersPrefix = "th-au-value-converters-"; | ||
private const string VkAuBindingBehaviorsPrefix = "th-au-binding-behaviors-"; | ||
|
||
private IDictionary<string, ModelExpression> _allModels; | ||
/// <summary> | ||
/// If attribute is foo and MVC Model member is Bar; th-au-bind-foo="Bar" | ||
/// To change binding type from default .bind; th-au-bind-foo.one-time="Bar" (other possibles are .one-way and .two-way) | ||
/// </summary> | ||
[HtmlAttributeName("th-au-all-models", DictionaryAttributePrefix = VkAuBindPrefix)] | ||
public IDictionary<string, ModelExpression> AllModels { | ||
get { | ||
return _allModels ?? | ||
(_allModels = new Dictionary<string, ModelExpression>(StringComparer.OrdinalIgnoreCase)); | ||
} | ||
set { | ||
_allModels = value; | ||
} | ||
} | ||
|
||
private IDictionary<string, string> _allValueConverters; | ||
/// <summary> | ||
/// Aurelia Value Converters to use for each binding. If multiple separate with |. | ||
/// To set for attribute foo: th-au-value-converters-foo="conv1" | ||
/// </summary> | ||
[HtmlAttributeName("th-au-all-value-converters", DictionaryAttributePrefix = VkAuValueConvertersPrefix)] | ||
public IDictionary<string, string> AllValueConverters { | ||
get { | ||
return _allValueConverters ?? | ||
(_allValueConverters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)); | ||
} | ||
set { | ||
_allValueConverters = value; | ||
} | ||
} | ||
|
||
private IDictionary<string, string> _allBindingBehaviors; | ||
/// <summary> | ||
/// Aurelia Binding Behaviours to use for each binding. If multiple separate with &. | ||
/// To set for attribute foo: th-au-binding-behaviors-foo="beh1" | ||
/// </summary> | ||
[HtmlAttributeName("th-au-all-binding-behaviors", DictionaryAttributePrefix = VkAuBindingBehaviorsPrefix)] | ||
public IDictionary<string, string> AllBindingBehaviors { | ||
get { | ||
return _allBindingBehaviors ?? | ||
(_allBindingBehaviors = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)); | ||
} | ||
set { | ||
_allBindingBehaviors = value; | ||
} | ||
} | ||
|
||
public override void Process(TagHelperContext context, TagHelperOutput output) | ||
{ | ||
foreach (KeyValuePair<string, ModelExpression> item in AllModels) | ||
{ | ||
string attributeName = item.Key; | ||
string bindType = "bind"; | ||
if (attributeName.Contains(".")) | ||
{ | ||
var parts = attributeName.Split('.'); | ||
attributeName = parts[0]; | ||
bindType = parts[1]; | ||
} | ||
|
||
string expression = BuildExpression(item.Value); | ||
|
||
string valueConverters = ""; | ||
if (AllValueConverters.ContainsKey(attributeName)) | ||
{ | ||
valueConverters = AllValueConverters[attributeName]; | ||
} | ||
|
||
string bindingBehaviors = ""; | ||
if (AllBindingBehaviors.ContainsKey(attributeName)) | ||
{ | ||
bindingBehaviors = AllBindingBehaviors[attributeName]; | ||
} | ||
|
||
expression = AddConvertersAndBehaviors(expression, valueConverters, bindingBehaviors); | ||
|
||
output.Attributes.SetAttribute(attributeName + "." + bindType, expression); | ||
} | ||
} | ||
|
||
public static string BuildExpression(ModelExpression model) | ||
{ | ||
string name = model.Name; | ||
|
||
if (String.IsNullOrEmpty(name)) | ||
{ | ||
throw new InvalidOperationException("AureliaGenericBindTagHelper could not resolve name from the given ModelExpression."); | ||
} | ||
|
||
string result = string.Empty; | ||
string[] parts = name.Split('.'); | ||
for (int i = 0; i < parts.Length; i++) | ||
{ | ||
if (i > 0) | ||
{ | ||
result += "."; | ||
} | ||
string part = parts[i][0].ToString().ToLowerInvariant() + parts[i].Substring(1); //Make camelCase; | ||
result += part; | ||
} | ||
result = "data." + result; //"data" is by convention the name of any MVC Model added as data to a client side model. | ||
return result; | ||
} | ||
|
||
public static string AddConvertersAndBehaviors(string bindExpression, string valueConverters, string bindingBehaviors) | ||
{ | ||
string result = bindExpression; | ||
|
||
if (!String.IsNullOrWhiteSpace(valueConverters)) | ||
{ | ||
result += " | " + valueConverters; | ||
} | ||
|
||
if (!String.IsNullOrWhiteSpace(bindingBehaviors)) | ||
{ | ||
result += " & " + bindingBehaviors; | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters