Skip to content

Commit

Permalink
Fixed ClickArguments to support precompilation in composite controls
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasherceg committed Feb 25, 2024
1 parent 4c1f8c1 commit 5bdb82b
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 27 deletions.
19 changes: 12 additions & 7 deletions src/Framework/Framework/Binding/BindingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,22 +256,27 @@ public static ParametrizedCode GetParametrizedCommandJavascript(this ICommandBin
/// <summary>
/// Gets command arguments parametrized code from the arguments collection.
/// </summary>
public static CodeParameterAssignment? GetParametrizedCommandArgs(DotvvmControl control, IEnumerable<object?> argumentsCollection)
public static CodeParameterAssignment? GetParametrizedCommandArgs(DotvvmControl control, IEnumerable<object?>? argumentsCollection)
{
var builder = new ParametrizedCode.Builder();
var isFirst = true;

builder.Add("[");
foreach (var arg in argumentsCollection)
if (argumentsCollection is not null)
{
if (!isFirst)
foreach (var arg in argumentsCollection)
{
builder.Add(",");
}
isFirst = false;
if (!isFirst)
{
builder.Add(",");
}

isFirst = false;

builder.Add(ValueOrBinding<object>.FromBoxedValue(arg).GetParametrizedJsExpression(control));
builder.Add(ValueOrBinding<object>.FromBoxedValue(arg).GetParametrizedJsExpression(control));
}
}

builder.Add("]");

return builder.Build(OperatorPrecedence.Max);
Expand Down
42 changes: 29 additions & 13 deletions src/Framework/Framework/Compilation/Styles/ResolvedControlHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using DotVVM.Framework.Binding;
Expand Down Expand Up @@ -134,20 +135,35 @@ public record PropertyTranslationException(DotvvmProperty property):
}

private static Type[] ImmutableContainers = new[] {
typeof(ImmutableArray<>), typeof(ImmutableList<>), typeof(ImmutableDictionary<,>), typeof(ImmutableHashSet<>), typeof(ImmutableQueue<>), typeof(ImmutableSortedDictionary<,>), typeof(ImmutableSortedSet<>), typeof(ImmutableStack<>)
typeof(ImmutableArray<>), typeof(ImmutableList<>), typeof(ImmutableHashSet<>), typeof(ImmutableQueue<>), typeof(ImmutableSortedSet<>), typeof(ImmutableStack<>)
};
internal static bool IsImmutableObject(Type type) =>
typeof(IBinding).IsAssignableFrom(type ?? throw new ArgumentNullException(nameof(type)))
|| type.GetCustomAttribute<HandleAsImmutableObjectInDotvvmPropertyAttribute>() is object
|| type.IsGenericType && ImmutableContainers.Contains(type.GetGenericTypeDefinition()) && type.GenericTypeArguments.All(IsImmutableObject);

public static bool IsAllowedPropertyValue([NotNullWhen(false)] object? value) =>
value is ValueOrBinding vob && IsAllowedPropertyValue(vob.UnwrapToObject()) ||
value is null ||
ReflectionUtils.IsPrimitiveType(value.GetType()) ||
value is HtmlGenericControl.AttributeList ||
IsImmutableObject(value.GetType()) ||
value is Array && ReflectionUtils.IsPrimitiveType(value.GetType().GetElementType()!);

public static bool IsAllowedPropertyValue([NotNullWhen(false)] object? value)
{
if (value is ValueOrBinding vob && IsAllowedPropertyValue(vob.UnwrapToObject()) ||
value is HtmlGenericControl.AttributeList ||
value is IBinding ||
value is null)
{
return true;
}

var type = value.GetType();
if (ReflectionUtils.IsPrimitiveType(type) ||
type.GetCustomAttribute<HandleAsImmutableObjectInDotvvmPropertyAttribute>() is not null)
{
return true;
}

// technically we should not allow Array as it can be modified, but we use it already on many places
if (value is Array ||
(type.IsGenericType && ImmutableContainers.Contains(type.GetGenericTypeDefinition())))
{
return ((IEnumerable)value).OfType<object>().All(IsAllowedPropertyValue);
}

return false;
}

public static ResolvedPropertySetter TranslateProperty(DotvvmProperty property, object? value, DataContextStack dataContext, DotvvmConfiguration? config)
{
Expand Down
7 changes: 3 additions & 4 deletions src/Framework/Framework/Controls/ButtonBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ public Command? Click
/// This property is typically used from the code-behind to allow sharing the same binding expressions among multiple buttons.
/// </summary>
[MarkupOptions(MappingMode = MappingMode.Exclude)]
public List<object?> ClickArguments
public object?[]? ClickArguments
{
get { return (List<object?>)GetValue(ClickArgumentsProperty)!; }
get { return (object?[])GetValue(ClickArgumentsProperty)!; }
set { SetValue(ClickArgumentsProperty, value); }
}
public static readonly DotvvmProperty ClickArgumentsProperty
= DotvvmProperty.Register<List<object?>, ButtonBase>(c => c.ClickArguments, null);
= DotvvmProperty.Register<object?[]?, ButtonBase>(c => c.ClickArguments, null);

/// <summary>
/// Gets or sets a value indicating whether the button is enabled and can be clicked on.
Expand Down Expand Up @@ -77,7 +77,6 @@ public TextOrContentCapability TextOrContentCapability
/// </summary>
public ButtonBase(string tagName) : base(tagName)
{
ClickArguments = new List<object>();
}


Expand Down
2 changes: 1 addition & 1 deletion src/Framework/Framework/Controls/GridViewColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public virtual void CreateHeaderControls(IDotvvmRequestContext context, GridView

var linkButton = new LinkButton();
linkButton.SetValue(ButtonBase.TextProperty, GetValueRaw(HeaderTextProperty));
linkButton.ClickArguments.Add(sortExpression);
linkButton.ClickArguments = new object?[] { sortExpression };
cell.Children.Add(linkButton);

linkButton.SetBinding(ButtonBase.ClickProperty, sortCommandBinding);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<body>

<!-- ko if: Customers()?.Items()?.length -->
<table data-bind="dotvvm-gridviewdataset: {'mapping':{},'dataSet':Customers()}">
<table data-bind="dotvvm-gridviewdataset: { dataSet: Customers(), mapping: {} }">
<thead>
<tr>
<th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@
"isCommand": true
},
"ClickArguments": {
"type": "System.Collections.Generic.List`1[[System.Object, CoreLibrary]]",
"type": "System.Object[]",
"mappingMode": "Exclude"
},
"Enabled": {
Expand Down

0 comments on commit 5bdb82b

Please sign in to comment.