Christian Gollhardt
Christian Gollhardt

Reputation: 17024

How do I change the Classtype of ModelExpression in TagHelpers?

I want to create a Tag Helper which accept some property names of a specific model.

public class DataTableColumnTagHelper : TagHelper
{
    public ModelExpression For { get; set; } //This is for ViewModel
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        base.Process(context, output);
    }
}

By default, above For is binding to the ViewModel. Is it somehow possible to bind it to another class?

I first tried to do it via a generic type parameter with DataTableColumnTagHelper<TModel>, but <data-table-column<SomeModel>> is not valid syntax.

I currently have it have it working this way:

Tag Helper:

public class DataTableColumnTagHelper : TagHelper
{
    public ModelExpression For { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "p";
        output.Content.SetContent(For.Metadata.PropertyName);
        base.Process(context, output);
    }
}

View Model

public class UserGroupViewModel : BaseViewModel
{
    public UserGroupTableItem TableItem => null;
}

View:

<data-table-column for="TableItem.Id"></data-table-column>
<data-table-column for="TableItem.Label"></data-table-column>
<data-table-column for="TableItem.PermissionQuantity"></data-table-column>

My goal is to remove the TableItem property, since it's only a dummy to make ModelExpression work.

Any suggestions?

Upvotes: 2

Views: 633

Answers (1)

Jeremy Lakeman
Jeremy Lakeman

Reputation: 11138

From your example; <data-table-column for="TableItem.Id">, razor assumes you mean Model.TableItem.Id. Razor will generate code like this to set the value of each TagHelper's ModelExpression properties;

ModelExpressionProvider.CreateModelExpression(ViewData, __model => __model.TableItem.Id);

(Source)

If you prefix your attribute value with @, the generated code drops the implicit __model. so you can bind the ModelExpression to any c# expression;

@t = Model.TableItem;
<data-table-column for="@t.Id">

I can't think of a way to make it any simpler, while still being strongly typed.

Upvotes: 2

Related Questions