Aspnetcore: Suggestion: Adding Directive

Created on 11 Oct 2018  路  9Comments  路  Source: dotnet/aspnetcore

I'd love to see the ability of supporting also directives, same principle as Angular.

Thanks!

affected-few area-blazor enhancement not-on-roadmap severity-minor

Most helpful comment

@asyncoder This one is a bit further down our backlog right now. We need to first land getting the basics of Razor Components into ASP.NET Core 3.0. But if anyone wants to submit some design proposals for what cross cutting directives in Blazor might look like that would be fine.

All 9 comments

Honestly, I think one of the serious advantage of Blazor compared to other frameworks is its simplicity : there is a small amount of concept in the framework (page / component). In the angular world you learn a new one every day (https://angular.io/guide/glossary).

When asking a feature maybe we could tell which case cannot be resolved with the current framework state instead of grabbing concept from others.

Do you have any case in mind where the current framework cannot help you ?

I wouldn't say grabbing features from others rather than taking advantages. However, the simplicity and reusing C# skills are one of the reasons that Blazor got my heart :-)

Directives are really powerful when you want for example to extend new features and behaviours to an existing components. Let's say that you have a native component "input" and you'd like it behaves somehow when the user focus on it. It wouldn't be so nice to create a new abstract component to do this and then you have to manage all others attributes including accessibility and so on.

Hope I made it clear.

Happy blazoring!

Agree, some concept of attribute directives (aka custom bindings in knockout) is critical. Components are good, but they don't go nearly far enough.

Any chance to have this feature ASAP? 馃檮
@danroth27

@asyncoder This one is a bit further down our backlog right now. We need to first land getting the basics of Razor Components into ASP.NET Core 3.0. But if anyone wants to submit some design proposals for what cross cutting directives in Blazor might look like that would be fine.

So I'd like to simply give some input about what I like and don't like about the general use of directives and how I feel would be a good investment:

  • They should be explicit

    • The MVC tag helpers are imo not explictit. You don't know what tag helper is available and you'll have to think of all the prefixes to add to make sure you don't overlap with another existing one or attribute.

      <label asp-for="Item.Name">Name</label>

    • Angular directives are explict. You directly say what directive should be applied. However, since they are simple attribtues could still overlap with existing attributes or other directives so you need again a prefix while we have namespaces for a reason.

      <button appConfirm [message]='"Are you sure?"'>Delete</button>

    • Proposal 1: I don't know if this is possible with razor, but explicitely invoking it could help to identify directives. This way there is no confusion about what this attribute does and you are not left with finding abbreviated and possibly confusing prefixes. Directives that have the same name can be prefixed by its namespace. In this example Confirm or ConfirmDirective should be the class name of the directive.

      <MyComponent @Confirm/> or <MyComponent @MyLibrary.Confirm/>

    • Proposal 2: Again, I don't know if this is possible, but since directives share a lot of common traits with C# attributes, we might find a way to apply them like that. Not as an html attribute, but as a C# one.

      @[Confirm]

      <MyComponent/>

  • They should be succinct

    • Angular directives can add as many parameters as they like. This eventually gives an overload of attributes and it gets hard to identify what attributes belongs to which component/directive. Does [message] belong to the directive of the component?

      <app-show-message appConfirm [message]="'Are you sure?'">Blah<app-show-message/>

    • Proposal: Only allow a single options object per directive:

      <MyComponent @MyDirective="@_myDirectiveOptions">

    • Note that if from the previous block proposal 2 is possible, this is obsolete since we simply apply how attributes normally get their options and adding multiple is also the same. This keeps them nicely seperated and easy to understand.

      @[MyDirective("message", Title = "Tile")]

      @[MyOtherDirective]

      <input/>

Feel free to comment or criticise.

@RemiBou why directives are sometimes preferred:

I want to extend the <select> attribute such that you can use it like this:
<select Items="@_items" Changed="@OnChanged"/>
Expected behavior is that options are generated automatically based on the collection _items and that I get notified and get the object back from this select rather than an ID as a string (i.e. OnChanged is an Action<TItem>).

This can still be easily implemented using a component. But now I want to style it and add the class attribute to the select. Blazor/Razor will now complain that the parameter class is not defined. Well, I could write a parameter class in the component to support this. But then I want to be able to hide it using the hidden attribute. So you'll have to add that paramter too etc.

This is the result of blazor components not existing in the DOM itself. Which keeps the DOM clean and readable, but now in this case also results in some responsibilities shifted to a child component since the parent has no way of editing it, or a lot of code needs to be added to the child component to support it. Both are not preferred in this case.

@didii:

  • They should be succinct

    • Angular directives can add as many parameters as they like. This eventually gives an overload of attributes and it gets hard to identify what attributes belongs to which component/directive. Does [message] belong to the directive of the component?
      <app-show-message appConfirm [message]="'Are you sure?'">Blah<app-show-message/>
    • Proposal: Only allow a single _options_ object per directive:
      <MyComponent @MyDirective="@_myDirectiveOptions">
    • _Note that if from the previous block proposal 2 is possible, this is obsolete since we simply apply how attributes normally get their options and adding multiple is also the same. This keeps them nicely seperated and easy to understand._
      @[MyDirective("message", Title = "Tile")]
      @[MyOtherDirective]
      <input/>

What about following?

<MyComponent @MyDirective(option1, option2)>
<MyComponent @MyDirective="(option1, option2)">
Was this page helpful?
0 / 5 - 0 ratings