5

I am trying to generate my own component with checkbox system to know if I need the attribute or not (of type int / float etc)

<input type="checkbox" @bind="isMinInt" />
@if (isMinInt == true) {
    <input type="number" @bind="MinInt"/>
}

So I would like to replace this @if:

@if(isMinInt == true) {
    <MyComponent @bind-Value="ValueInt" Min="@MinInt"/>
} else {
    <MyComponent @bind-Value="ValueInt"/>
}

by something like

<MyComponent @bind-Value="ValueInt" 
             @if(isMinInt == true ? Min="@MinInt" : String.Empty />

because I will have many attributes on my component and I would like to make it simplier

EDIT + Solution

Now using the @attributes:

<input type="checkbox" @bind="isMinInt" />
@if (isMinInt == true) {
   <input type="number" @bind="MinInt" />
}

<MyComponent @bind-Value="ValueInt" @attributes="GetAttributesInt()" />

@code {
    private bool isMinInt = false;
    private int MinInt;

    private IDictionary<string, object> GetAttributesInt() {
       var dict = new Dictionary<string, object>() { };
       if (isMinInt)
         dict.Add("Min", MinInt);
       return dict;
    }
}

EDIT + Solution 2

Now using the @attributes:

<input type="checkbox" @bind="isMinInt" />
@if (isMinInt == true) {
   <input type="number" @bind="MinInt" />
}

<MyComponent @bind-Value="ValueInt" @attributes="GetAttributesInt()" />

@code {
    private bool isMinInt = false;
    private int MinInt;

    private IDictionary<string, object> GetAttributesInt() {
       var dict = new Dictionary<string, object>() { };
       dict["Min"] = this.isMinInt ? MinInt : Int32.MinValue;
       return dict;
    }
}

The reason why I'm using Int32.MinValue it's because MyComponent correspond to an <input type="number"> where his min is bind to my MinInt, so if I use 0 in the place of Int32.MinValue it won't allow me to go for negative numbers.

2 Answers 2

2

I will have many attributes on my component and I would like to make it simplier

You can't do that directly. However, as a walkaround, you can use the @attributes to bind attributes dynamically. For example:

<MyComponent @bind-Value="ValueInt" @attributes="@a_dictionary_expression"  />

Where @a_dictionary_expression is a C# expression that can be evaluated at runtime. What's more, you can even create a custom function to calculate the dictionary:

<MyComponent @bind-Value="ValueInt" @attributes="getAttributes()"  /gt;

@code {
    ... 
    private IDictionary getAttributes()
    {
        var dict = new Dictionary(){};
        if(isMinInt) {
            dict.Add("Min", $"{MinInt}");
        }   // this will introduce a bug, see Edit2 for more details
        return dict ;
    }
}

[Edit]: Here's a way to render the attributes within a single line

<input @bind-Value="ValueInt" @attributes="@(isMinInt? new Dictionary<string,object>{ Min= @Min} : new Dictionary<string,object>{})" />

[Edit2]

The above code will introduce a bug that the MyComponent is not updated correctly. The reason is the parameters of <MyComponent> received from previous @attributes is not automatically cleared when a new @attributes received.

For example,

  1. the first time @attributes is {Min=1}, and it results in a statement:
    MyComponent.Min=1;
    
  2. The second time @attributes is {}, because there's no attribute inside it, it won't assign parameters for it, thus the MyComponent.Min remains the same.

To fix that, change the above code as below:

private IDictionary<string, object> GetAttributesInt() {
    var dict = new Dictionary<string, object>() { };
    dict["Min"] = this.isMinInt ? MinInt : 0 ;
    return dict;
}
Sign up to request clarification or add additional context in comments.

7 Comments

I'm getting error when using custom function: Unable to set property 'Min' on object of type Int32 The error was: Specified cast is not valid. ---> System.InvalidCastException: Specified cast is not valid.
@yToxide Please change it to dict.Add("Min", MinInt);
Thanks, and how could I remove it if my isMinInt come back to false after ?
@yToxide You don't have to remove it manually. Every time the data is changed, you should get a new dictionary, thus a new @attributes, and finally you'll get a new UI rendered. Always follow the pattern : Change Data ---> UI Updated
it's not working, when i uncheck my checkbox, isMinInt go back to false but my component still keep the value of Min
|
2

I used this simple solution and it work, hope this help you too:

<input id="@InputId"  aria-labelledby="@(!string.IsNullOrWhiteSpace(InputId) ? "this is test" : null)">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.