BlazorWebFormsComponents icon indicating copy to clipboard operation
BlazorWebFormsComponents copied to clipboard

Default the Context for a control to "Item"

Open csharpfritz opened this issue 5 years ago • 15 comments

Need to do some research into how Blazor sets "@context" as the default context variable name for child components. To maintain Web Forms compatibility we should reset the default for THESE COMPONENTS ONLY to @Item

csharpfritz avatar Dec 12 '19 17:12 csharpfritz

Are you wanting to not have to convert explicitly

  <ListView 
  @ref="simpleListView"
  runat="server"
  Context="Item"
  SelectMethod="simpleListView_GetData"
  ItemType="SharedSampleObjects.Models.Widget">
  <ItemTemplate>
    <tr>
    <td>@Item.Id </td>
    <td>@Item.Name </td>
    <td>@Item.Price.ToString("c") </td>
    <td>@Item.LastUpdate.ToString("d") </td>
    </tr>
  </ItemTemplate>

where the Context="Item" changes @context to @item

What you want is for the BlazorWebFormsComponents.ListView to be able to recognize the @item notation without the need for the Context="Item" markup in the client code.

You'd then have

<ListView 
  @ref="simpleListView"
  runat="server"
  SelectMethod="simpleListView_GetData"
  ItemType="SharedSampleObjects.Models.Widget">
  <ItemTemplate>
    <tr>
    <td>@Item.Id </td>
    <td>@Item.Name </td>
    <td>@Item.Price.ToString("c") </td>
    <td>@Item.LastUpdate.ToString("d") </td>
    </tr>
  </ItemTemplate>

grleachman avatar Feb 07 '20 01:02 grleachman

Precisely! This helps the syntax adhere to the standard used in Web Forms and eliminates another piece of Blazor specific syntax that needs to be added when migrating from ASP.NET Web Forms.

csharpfritz avatar Feb 07 '20 10:02 csharpfritz

Oooh! so we COULD override the Context parameter somewhere in the stack to force it.

Need to research a little further

csharpfritz avatar Feb 07 '20 21:02 csharpfritz

The commit is actually against an internal ComponentTagHelper… but it gives a place to start.

L276

however it all looks very internal.

Without thinking about how this might actually be implemented, a possible dirty first step could be

  • intercept the Blazor rendering
  • replace @item with @context
  • pass that back into the Blazor renderer

which sounds like a "simple" decorator.

grleachman avatar Feb 07 '20 21:02 grleachman

BlazorWebFormComponents needs to be able to access the TagHelperDescriptorBuilder here, and apply the same behaviour as the CreateContextParameter with the childContentName = item

private void CreateContextParameter(TagHelperDescriptorBuilder builder, string childContentName)
{
    builder.BindAttribute(b =>
    {
        b.Name = "Context";
        b.TypeName = typeof(string).FullName;
        b.Metadata.Add(BlazorMetadata.Component.ChildContentParameterNameKey, bool.TrueString);
        if (childContentName == null)
        {
            b.Documentation = Resources.ChildContentParameterName_TopLevelDocumentation;
        }
        else
        {
            b.Documentation = string.Format(Resources.ChildContentParameterName_Documentation, childContentName);
        }
    });
}

grleachman avatar Feb 07 '20 21:02 grleachman

The test for this in Blazor : ChildContentRazorIntegrationTest see :

  • Render_MultipleChildContent_ContextParameterOnComponent
  • Render_MultipleChildContent_ContextParameterOnComponent_SetsSameName

image

Notice how the Context="Item" attribute does not actually appear in the component's Frames.

grleachman avatar Feb 08 '20 13:02 grleachman

so.. could we override this by adding a string Context {get;set;} to a base class and default it to Item? Hmm... feels like a good experiment.

Update: doesn't work. Tagging @rynowak and @danroth27 for insight

csharpfritz avatar Feb 08 '20 14:02 csharpfritz

We deliberately do not allow a component to set the name of context. This creates a guessing game, where different components in the ecosystem have different behaviors, and users have to figure it out for each library they use.

rynowak avatar Feb 08 '20 19:02 rynowak

We’d like to extend the defaults to allow the “Item” that was the default in web forms to be usable as a default as well.

Jeff

On Feb 8, 2020, at 14:35, Ryan Nowak [email protected] wrote:

 We deliberately do not allow a component to set the name of context. This creates a guessing game, where different components in the ecosystem have different behaviors, and users have to figure it out for each library they use.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

csharpfritz avatar Feb 08 '20 19:02 csharpfritz

While it would be fun to research this further, and find some point of DI that could subvert the Blazor teams deliberate enforcement of the context syntax. I think there might be better places to invest in.

A ticket should be created to document this explicit requirement for conversion.

grleachman avatar Feb 08 '20 22:02 grleachman

it might be nice if the Blazor team add some specific WebFormsSupport(). services.AddWebFormsSupport(); This might do things like …

  • override the internal ?TagHelper? that manages / sets the Context="Item"

grleachman avatar Feb 10 '20 23:02 grleachman

#49 another unsupported (but we'll do it if the community shouts loud enough)

grleachman avatar Feb 12 '20 00:02 grleachman

I think your work on DataBinding.Eval has resolved this. ??

grleachman avatar Feb 18 '20 01:02 grleachman

Unfortunately I don't think it will. Eval returns a RenderFragment that gets rendered as a string.

We would need to implement an Item property that returns the type of @context.

csharpfritz avatar Feb 18 '20 02:02 csharpfritz