10
votes

I am learning Blazor. I have no experience with component-based programming.

I have two components: a DateRangePicker and a RadzenCheckBox.

<RadzenFieldset Text="Test Component">
    <DateRangePicker @ref="calendar" />
    <div>
        <Radzen.Blazor.RadzenCheckBox TValue="bool" Change="@((args) => txtBoxChange(args))" />
        <RadzenLabel Text="Check" />
    </div>
</RadzenFieldset>

Now, the requirement is simple. If the checkbox is clicked, show two calendars and show one calendar if it's unchecked.

I wrote the following code:

@code{
    DateRangePicker calendar;

    public void txtBoxChange(bool args) 
    {
        if (args == true) //shows one calendar when checked
            calendar.ShowOnlyOneCalendar = true;
        else //shows two calendars when unchecked
            calendar.ShowOnlyOneCalendar = false;
    }
}

This works fine.

But I get a warning:

Component parameter 'ShowOnlyOneCalendar' should not be set outside of its component.

I have read some blogs about this warning, which suggest making parent and child component relationship for communication between components. But these are not parent and child.

What am I doing wrong? What is the best way to achieve such a requirement and not have this warning?

1
Since .NET Core 3.1, you can put the content of your @code { ... } block into separate code-behind files. Makes it much cleaner.Uwe Keim
Correct way to mutate a component property in blazor: stackoverflow.com/questions/59381788/…enet

1 Answers

8
votes

What am I doing wrong?

Instead of using an imperative programming (component.Parameter1=v1) way, a Component Parameter is supposed be passed in declarative syntax :

<Component Parameter1="@v1"  Parameter2="@v2" />

Note you're assigning values to [Parameter] directly:

calendar.ShowOnlyOneCalendar = true;

That's why Blaozr complains. In other words, you need change it in following way:

<DateRangePicker ShowOnlyOneCalendar="@showOnlyOne"  />

How to fix

Always follow this pattern like other SPA:

      (render)
Data -----------> View

For example, your code could be rewritten as below:

<DateRangePicker ShowOnlyOneCalendar="@flag" />
...

@code{
    private bool flag = false;
    public void txtBoxChange(bool args)=> flag = args;
}

(Here we have a flag data, and we should render the view according to the data)

Or if you do want to use an imperative programming way, you need to invoke a method and avoid assigning values to the [Parameter] properties directly.

<DateRangePicker @ref="calendar" />
...


@code{
    DateRangePicker calendar;
    public void txtBoxChange(bool args) 
    {
         calendar.A_Wrapper_Method_That_Changes_The_Parameter(args);
         // as suggested by @Uwe Keim, 
         //    `InvokeAsync(StateHasChanged)` is better than `StateHasChanged()`
         InvokeAsync(StateHasChanged); 
    }
}