« Blazor component » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
(27 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
[[Category:Blazor]]
[[Category:Blazor]]
= Links =
* [https://docs.microsoft.com/en-us/aspnet/core/blazor/components Components]
* [https://github.com/dotnet/aspnetcore/tree/main/src/Components/Web/src/Forms Framework form controls source code]
= Separate library =
<kode lang='bash'>
dotnet new razorclasslib -o MyOwnComponents
</kode>
{{warn | It is not possible to import external css library.}}
= Basic component =
= Basic component =
<filebox fn='Components/MyComponent.razor'>
<filebox fn='Components/MyComponent.razor'>
Ligne 76 : Ligne 86 :
}
}
</filebox>
</filebox>
= [https://docs.microsoft.com/en-us/aspnet/core/blazor/components/cascading-values-and-parameters?view=aspnetcore-5.0 Cascading values and parameters] =
Set a value for the component hierarchy from an ancestor component to any number of descendent components.
<filebox fn='Pages/Index.razor'>
@* BtnStyle will be available in MyComponent and all its descendent components *@
<CascadingValue Value="btnStyle" IsFixed="true">
    <MyComponent />
</CascadingValue>
@code {
    string btnStyle = "btn-success";
}
</filebox>
<filebox fn='Components/MyComponent.razor.cs'>
// match between the cascading value and the cascading parameter is made by the type (string) and not by the property name
[CascadingParameter]
public string BtnStyle { get; set; }
</filebox>
== [https://docs.microsoft.com/en-us/aspnet/core/blazor/webassembly-performance-best-practices?view=aspnetcore-5.0#ensure-cascading-parameters-are-fixed Ensure cascading parameters are fixed] ==
If the {{boxx|IsFixed}} value is {{boxx|true}} ({{boxx|false}} by default), then receipients receive the initial value but do not set up any subscription to receive updates. In this case, each {{boxx|[CascadingParameter]}} is lightweight and no more expensive than a regular {{boxx|[Parameter]}}.<br>
So wherever possible, you should use {{boxx|1=IsFixed="true"}} on cascaded values. You can do this whenever the value being supplied doesn't change over time.
= [https://docs.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-5.0#capture-references-to-components Capture references to components] =
Component references provide a way to reference a component instance for issuing commands.
<filebox fn='Pages/Index.razor'>
<MyComponent @ref="myComponent" />
<button @onclick="@(() => myComponent.MyMethod())">
    Call <code>MyComponent.MyMethod</code>
</button>
@code {
    private MyComponent myComponent;
}
</filebox>
= [https://docs.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-5.0#attribute-splatting-and-arbitrary-parameters Attribute splatting and arbitrary parameters] =
Instead of having multiple parameters, have one parameter of type dictionary to pass multiple attributes.
<filebox fn='Components/MyComponent.razor.cs'>
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object> AdditionalAttributes { get; set; }
protected string CssClass
{
    get
    {
        var cssClass = string.Empty;
        if (AdditionalAttributes != null &&
            AdditionalAttributes.TryGetValue("class", out var classAttribute))
        {
            cssClass = Convert.ToString(classAttribute, CultureInfo.InvariantCulture);
        }
        return cssClass;
    }
}
</filebox>
<filebox fn='Pages/Index.razor'>
<MyComponent class="myClass"></MyComponent>
</filebox>
= Custom components =
== Input text with clear button ==
<filebox fn='InputTextClear.razor'>
@inherits InputBase<string>
<input @attributes="AdditionalAttributes" class="@CssClass" @bind="CurrentValueAsString" @bind:event="@BindEvent" @ref="Element" />
<span class="fas fa-times-circle" @onclick="Clear"></span>
</filebox>
<filebox fn='InputTextClear.razor.cs'>
public partial class InputTextClear3 : InputBase<string>
{
    public ElementReference Element { get; private set; }
    protected string BindEvent
    {
        get
        {
            var bindEvent = "onchange";
            if (AdditionalAttributes != null &&
                AdditionalAttributes.TryGetValue("bind-event", out var bindEventAttribute))
            {
                var bindEventAttributeAsString = Convert.ToString(bindEventAttribute, CultureInfo.InvariantCulture);
                if (bindEventAttributeAsString == "onchange" || bindEventAttributeAsString == "oninput")
                {
                    bindEvent = bindEventAttributeAsString;
                }
            }
            return bindEvent;
        }
    }
    protected override bool TryParseValueFromString(
        string value,
        out string result,
        out string validationErrorMessage)
    {
        result = value;
        validationErrorMessage = null;
        return true;
    }
    private async Task Clear()
    {
        CurrentValue = string.Empty;
        await Element.FocusAsync();
    }
}
</filebox>
<filebox fn='InputTextClear.razor.css'>
input {
    margin-right: -1.3rem;
    padding-right: 1.3rem;
}
i {
    font-size: smaller;
    vertical-align: middle;
    cursor: pointer;
}
</filebox>
<kode lang='html'>
<InputTextClear @bind-Value="input" bind-event="oninput" id="id" class="class"></InputTextClear3>
</kode>

Dernière version du 1 août 2021 à 20:18

Links

Separate library

Bash.svg
dotnet new razorclasslib -o MyOwnComponents
It is not possible to import external css library.

Basic component

Components/MyComponent.razor
<h1>Test</h1>
<p>@ChildContent</p>
Components/MyComponent.razor.cs
public partial class MyComponent : ComponentBase
{
    [Parameter]
    public RenderFragment ChildContent { get; set; }
}
Components/MyComponent.razor.css
h1 {
    color: coral;
}
Pages/Index.razor
@page "/"
@using Component.Components

<MyComponent>
    test !!!
</MyComponent>

Callback event

Components/MyComponent.razor.cs
[Parameter]
public EventCallback<string> Callback { get; set; }

private string description;

private async Task UpdateDescription()
{
    await Callback.InvokeAsync(description);
}
Pages/Index.razor
<MyComponent Callback="MyComponentCallback" />

@code {
    void MyComponentCallback(string description)
    {

    }
}

Binding with component parameters

Components/MyComponent.razor.cs
[Parameter]
public string Description { get; set; }

// name of the EventCallback has to be [PropertyName]Changed
[Parameter]
public EventCallback<string> DescriptionChanged { get; set; }

private async Task UpdateDescription()
{
    await DescriptionChanged.InvokeAsync(description);
}
Pages/Index.razor
@* two ways binding of the component parameter Description with the local field description *@
<MyComponent @bind-Description="description" />

@code {
    private string description = "Text";
}

Cascading values and parameters

Set a value for the component hierarchy from an ancestor component to any number of descendent components.

Pages/Index.razor
@* BtnStyle will be available in MyComponent and all its descendent components *@
<CascadingValue Value="btnStyle" IsFixed="true">
    <MyComponent />
</CascadingValue>

@code {
    string btnStyle = "btn-success";
}
Components/MyComponent.razor.cs
// match between the cascading value and the cascading parameter is made by the type (string) and not by the property name
[CascadingParameter]
public string BtnStyle { get; set; }

Ensure cascading parameters are fixed

If the IsFixed value is true (false by default), then receipients receive the initial value but do not set up any subscription to receive updates. In this case, each [CascadingParameter] is lightweight and no more expensive than a regular [Parameter].
So wherever possible, you should use IsFixed="true" on cascaded values. You can do this whenever the value being supplied doesn't change over time.

Capture references to components

Component references provide a way to reference a component instance for issuing commands.

Pages/Index.razor
<MyComponent @ref="myComponent" />

<button @onclick="@(() => myComponent.MyMethod())">
    Call <code>MyComponent.MyMethod</code>
</button>

@code {
    private MyComponent myComponent;
}

Attribute splatting and arbitrary parameters

Instead of having multiple parameters, have one parameter of type dictionary to pass multiple attributes.

Components/MyComponent.razor.cs
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object> AdditionalAttributes { get; set; }

protected string CssClass
{
    get
    {
        var cssClass = string.Empty;

        if (AdditionalAttributes != null &&
            AdditionalAttributes.TryGetValue("class", out var classAttribute))
        {
            cssClass = Convert.ToString(classAttribute, CultureInfo.InvariantCulture);
        }

        return cssClass;
    }
}
Pages/Index.razor
<MyComponent class="myClass"></MyComponent>

Custom components

Input text with clear button

InputTextClear.razor
@inherits InputBase<string>

<input @attributes="AdditionalAttributes" class="@CssClass" @bind="CurrentValueAsString" @bind:event="@BindEvent" @ref="Element" />
<span class="fas fa-times-circle" @onclick="Clear"></span>
InputTextClear.razor.cs
public partial class InputTextClear3 : InputBase<string>
{
    public ElementReference Element { get; private set; }

    protected string BindEvent
    {
        get
        {
            var bindEvent = "onchange";

            if (AdditionalAttributes != null &&
                AdditionalAttributes.TryGetValue("bind-event", out var bindEventAttribute))
            {
                var bindEventAttributeAsString = Convert.ToString(bindEventAttribute, CultureInfo.InvariantCulture);
                if (bindEventAttributeAsString == "onchange" || bindEventAttributeAsString == "oninput")
                {
                    bindEvent = bindEventAttributeAsString;
                }
            }

            return bindEvent;
        }
    }

    protected override bool TryParseValueFromString(
        string value,
        out string result,
        out string validationErrorMessage)
    {
        result = value;
        validationErrorMessage = null;
        return true;
    }

    private async Task Clear()
    {
        CurrentValue = string.Empty;
        await Element.FocusAsync();
    }
}
InputTextClear.razor.css
input {
    margin-right: -1.3rem;
    padding-right: 1.3rem;
}

i {
    font-size: smaller;
    vertical-align: middle;
    cursor: pointer;
}
Html.svg
<InputTextClear @bind-Value="input" bind-event="oninput" id="id" class="class"></InputTextClear3>