admin管理员组

文章数量:1289490

I have a .NET 9 Blazor project that contains a server and a client. In the client project, I have many forms. Those forms have many repetitive sections and some repetitive questions. For example, there is a dropdown list for Channels (like what you hear about me, and the options are Bing, Google, Friends, and so on).

I want to anize those fields better to avoid redundant code. To simplify, I have a main Razor page:

<EditForm EditContext="_context" OnSubmit="SubmitForm" Enhance>
    <InitialForm Client="@Client" Session="@Session" />
</EditForm>

@code {
    Domain.Client? Client;
    Domain.ClientSession? Session;

    protected override async Task OnInitializedAsync()
    {
        _context = new EditContext(Session);
    }

    public void Save() {
        // Client and Session save
    }
}

The Client and Session models are like this:

public class Client 
{
    public string? PhobiasNote { get; set; }
}

public class ClientSession
{
    public SessionInitial? SessionInitial { get; set; }
}

public class SessionInitial
{
    public bool HasPhobias { get; set; }
    public IList<Phobia>? Phobias { get; set; }
}

Then, the InitialForm is quite a list of inputs. This code is working.

<FormFieldSet>
    <ToggleButtonGroup @bind-Value="@Session.HasPhobias" />
    <Autocomplete SearchMethod="GetPhobias"
                  @bind-Values="Session.Phobias"
                  EnableDropDown="true"
                  MinimumLength="2"
                  AddItemOnEmptyResultMethod="PhobiaAddedMethod"
                  placeholder="@CommonStrings.SearchPhobias">
        <SelectedTemplate Context="rl">
            @rl.Name
        </SelectedTemplate>
        <ResultTemplate Context="rl">
            @rl.Name
        </ResultTemplate>
    </Autocomplete>
    <InputTextArea @bind-Value="@Client.PhobiasNote" />
    <span class="form-field-error">
        <ValidationMessage For="@(() => Session.Phobias)" />
    </span>
</FormFieldSet>

@code {
    [Parameter, EditorRequired] public SessionInitial? Session { get; set; }
    [Parameter, EditorRequired] public Client? Client { get; set; }
}

The logic of the last Razor is to collect info from the user and save it in the Session or Client object. When there is a change, I see the change in the main object.

For example, if I want to save the objects, in the function Save I can see the objects with the new values. I hope it is clear so far.

Now, because the Autocomplete for this particular kind is quite common, I want to create a Razor component and pass only the field where to save the data. So, the component is called PhobiaSelection and looks like this

<Autocomplete SearchMethod="GetPhobias"
              @bind-Values="Phobias"
              EnableDropDown="true"
              MinimumLength="2"
              AddItemOnEmptyResultMethod="PhobiaAddedMethod"
              placeholder="@CommonStrings.SearchPhobias">
    <SelectedTemplate Context="rl">
        @rl.Name
    </SelectedTemplate>
    <ResultTemplate Context="rl">
        @rl.Name
    </ResultTemplate>
</Autocomplete>

@code {
    [Parameter, EditorRequired] public IList<Phobia>? Phobias { get; set; } = default!;
}

With this component, the InitialForm is now more readable and easier

<FormFieldSet>
    <ToggleButtonGroup @bind-Value="@Session.HasPhobias" />
    <PhobiaSelection Phobias="Session.Phobias" />
    <InputTextArea @bind-Value="@Client.PhobiasNote" />
    <span class="form-field-error">
        <ValidationMessage For="@(() => Session.Phobias)" />
    </span>
</FormFieldSet>

@code {
    [Parameter, EditorRequired] public SessionInitial? Session { get; set; }
    [Parameter, EditorRequired] public Client? Client { get; set; }
}

The problem is that in this case if the user selects anything, there are no changes in the variable Session. I can see that in the PhobiaSelection the value changes but this is not changing.

Why doesn't the last component (called PhobiaSelection) update the value in the Session?

Update

Although I changed the EventCallback and the OnPhobiasChanged with both EventCallback<IList<Phobia>> or EventCallback<IList<Phobia>?> everywhere, I still get this error.

and this is what I see on ValuesChanged

and this is another try

I have a .NET 9 Blazor project that contains a server and a client. In the client project, I have many forms. Those forms have many repetitive sections and some repetitive questions. For example, there is a dropdown list for Channels (like what you hear about me, and the options are Bing, Google, Friends, and so on).

I want to anize those fields better to avoid redundant code. To simplify, I have a main Razor page:

<EditForm EditContext="_context" OnSubmit="SubmitForm" Enhance>
    <InitialForm Client="@Client" Session="@Session" />
</EditForm>

@code {
    Domain.Client? Client;
    Domain.ClientSession? Session;

    protected override async Task OnInitializedAsync()
    {
        _context = new EditContext(Session);
    }

    public void Save() {
        // Client and Session save
    }
}

The Client and Session models are like this:

public class Client 
{
    public string? PhobiasNote { get; set; }
}

public class ClientSession
{
    public SessionInitial? SessionInitial { get; set; }
}

public class SessionInitial
{
    public bool HasPhobias { get; set; }
    public IList<Phobia>? Phobias { get; set; }
}

Then, the InitialForm is quite a list of inputs. This code is working.

<FormFieldSet>
    <ToggleButtonGroup @bind-Value="@Session.HasPhobias" />
    <Autocomplete SearchMethod="GetPhobias"
                  @bind-Values="Session.Phobias"
                  EnableDropDown="true"
                  MinimumLength="2"
                  AddItemOnEmptyResultMethod="PhobiaAddedMethod"
                  placeholder="@CommonStrings.SearchPhobias">
        <SelectedTemplate Context="rl">
            @rl.Name
        </SelectedTemplate>
        <ResultTemplate Context="rl">
            @rl.Name
        </ResultTemplate>
    </Autocomplete>
    <InputTextArea @bind-Value="@Client.PhobiasNote" />
    <span class="form-field-error">
        <ValidationMessage For="@(() => Session.Phobias)" />
    </span>
</FormFieldSet>

@code {
    [Parameter, EditorRequired] public SessionInitial? Session { get; set; }
    [Parameter, EditorRequired] public Client? Client { get; set; }
}

The logic of the last Razor is to collect info from the user and save it in the Session or Client object. When there is a change, I see the change in the main object.

For example, if I want to save the objects, in the function Save I can see the objects with the new values. I hope it is clear so far.

Now, because the Autocomplete for this particular kind is quite common, I want to create a Razor component and pass only the field where to save the data. So, the component is called PhobiaSelection and looks like this

<Autocomplete SearchMethod="GetPhobias"
              @bind-Values="Phobias"
              EnableDropDown="true"
              MinimumLength="2"
              AddItemOnEmptyResultMethod="PhobiaAddedMethod"
              placeholder="@CommonStrings.SearchPhobias">
    <SelectedTemplate Context="rl">
        @rl.Name
    </SelectedTemplate>
    <ResultTemplate Context="rl">
        @rl.Name
    </ResultTemplate>
</Autocomplete>

@code {
    [Parameter, EditorRequired] public IList<Phobia>? Phobias { get; set; } = default!;
}

With this component, the InitialForm is now more readable and easier

<FormFieldSet>
    <ToggleButtonGroup @bind-Value="@Session.HasPhobias" />
    <PhobiaSelection Phobias="Session.Phobias" />
    <InputTextArea @bind-Value="@Client.PhobiasNote" />
    <span class="form-field-error">
        <ValidationMessage For="@(() => Session.Phobias)" />
    </span>
</FormFieldSet>

@code {
    [Parameter, EditorRequired] public SessionInitial? Session { get; set; }
    [Parameter, EditorRequired] public Client? Client { get; set; }
}

The problem is that in this case if the user selects anything, there are no changes in the variable Session. I can see that in the PhobiaSelection the value changes but this is not changing.

Why doesn't the last component (called PhobiaSelection) update the value in the Session?

Update

Although I changed the EventCallback and the OnPhobiasChanged with both EventCallback<IList<Phobia>> or EventCallback<IList<Phobia>?> everywhere, I still get this error.

and this is what I see on ValuesChanged

and this is another try

Share Improve this question edited Feb 21 at 0:37 Enrico asked Feb 20 at 15:35 EnricoEnrico 6,26611 gold badges78 silver badges176 bronze badges 1
  • Since you are using multiple custom Razor components, could you create a minimal sample to reproduce the issue so that we can debug and assist you more easily? – Zhi Lv Commented Feb 24 at 8:27
Add a comment  | 

1 Answer 1

Reset to default 1

The problem is probably because you're no longer binding Session.Phobias to the Autoselect values in your PhobiaSelection component.

Change your PhobiaSelection component:

Add:

[Parameter] public EventCallback<IList<Phobia>?> PhobiasChanged { get; set; }

async Task OnPhobiasChanged(IList<Phobia>? changedPhobias)
{
   await PhobiasChanged.InvokeAsync(changedPhobias);
}

This makes Phobias in your PhobiaSelection component bindable.

Change

<Autocomplete SearchMethod="GetPhobias"
              @bind-Values="Phobias"
              ...

to

<Autocomplete SearchMethod="GetPhobias"
              Values="Phobias"
              ValuesChanged="OnPhobiasChanged"
          ...

This will call OnPhobiasChanged which then raised the EventCallback when something changes, which you'll bind in the parent by changing:

<PhobiaSelection Phobias="Session.Phobias" />

to

<PhobiaSelection @bind-Phobias="Session.Phobias" />

This will then bind the PhobiaSelection selections to Session.Phobias

本文标签: cBlazor with EditForm doesn39t work with componentStack Overflow