Blazor (Razor Components) Обновить дочерний компонент из родительского компонента

У меня есть простой дочерний компонент Blazor (MyModal), например:

<div class="modal">
    <h3>@Title</h3>
    @BodyTemplate
</div>

@code
{
    [Parameter] string Title { get; set; }
    [Parameter] RenderFragment BodyTemplate { get; set; }
}

В моем родительском компоненте я называю это так:

<MyModal Title="Super Cool Modal">
        <BodyTemplate>
            @MyObject.Name
        </BodyTemplate>
</MyModal>

public MyObject MyObject { get; set; } = new MyObject();

Позже, после того, как страница изначально отрендерена, я обновляю MyObject но сам дочерний компонент ссылается @MyObject.Name никогда не обновляет

Кажется, я должен принудительно обновить дочерний объект после того, как я обновил объект (StateHasChanged) но не уверен, как это сделать с этим примером.

6 ответов

Вы можете попробовать это

Ребенок

Создайте общедоступный метод обновления, который вы можете вызывать из родительского

<div class="modal">
    <h3>@Title</h3>
    @BodyTemplate
</div>

@code
{
    [Parameter] string Title { get; set; }
    [Parameter] RenderFragment BodyTemplate { get; set; }

    public void RefreshMe()
    {
        StateHasChanged();
    }
}

Родитель

Вызов дочернего метода обновления

<MyModal Title="Super Cool Modal"
         @ref="ChildComponent">
        <BodyTemplate>
            @MyObject.Name
        </BodyTemplate>
</MyModal>
@code
{
   public MyObject MyObject { get; set; } = new MyObject();
   protected UploadDownloadComponent ChildComponent;

   //Call this method to update the child
   private void Change(TreeEventArgs args)
   {
       ChildComponent.RefreshMe();
   }
}

Вы можете просто использовать CascadingParameter.

В родительском компоненте просто вызовите дочерний компонент следующим образом:

      <CascadingValue Value="selectedChats[0].Id" Name="chatID">
     <AdminChatComponent> </AdminChatComponent>
</CascadingValue>

Дочерний компонент:

      [CascadingParameter(Name ="chatID")]
public string chatID { get; set; }

После этого все, что вам нужно сделать, это просто создать метод OnParametersSetAsync в дочернем компоненте и просто привязать свое значение к родительскому компоненту. В моем случае я привязал свое значение к выбору строки datagrid.

После этого всякий раз, когда привязанное значение изменяется в родительском компоненте, ваш дочерний компонент также запускает метод OnParametersSetAsync.

Поскольку <MyModal> имеет RenderFragment параметр достаточно позвонить StateHasChanged() в родительском компоненте он пересчитает и отобразит все дочерние компоненты с параметрами из родительского.

Вы можете выполнить «OnParametersSetAsync()» для дочернего компонента:

Родительский компонент:<childCompoment param="@paramParent" />

Дочерний компонент:

[Параметр]public string param{get;set;}

защищенное переопределение асинхронной задачи OnInitializedAsync() {await Refresh ();}

асинхронное обновление задачи (){}

Примечание: ваш шаблонный компонент был сделан неправильно, а также то, как вы его используете. Пожалуйста, запустите предоставленный мною код, убедитесь, что он работает, и просмотрите внесенные мной изменения. Если у вас есть вопросы, не стесняйтесь спрашивать.

Ваш код должен выглядеть примерно так:

MyModal

<div class="modal">
    <h3>@Title</h3>
    @BodyTemplate (MyObject)
</div>

@code
{
    [Parameter] string Title { get; set; }
    [Parameter] RenderFragment BodyTemplate { get; set; }
    [Parameter] MyObject MyObject{ get; set; }
}

использование

<MyModal Title="Super Cool Modal" MyObject="@MyObject">
        <BodyTemplate>
            @context.Name
        </BodyTemplate>
</MyModal>

public MyObject MyObject { get; set; } = new MyObject(); 

Надеюсь это поможет...

У меня есть другой пример со сложным объектом параметра, который необходимо сериализовать в модель формы.

OnParametersSetAsync() обновит дочерний компонент при изменении параметра.

Нам нужно привязать дочерний параметр с помощью @ bind-Job="_job"

Родитель:

      <div class="tab-pane active" id="kt_job_tab_1">
    <JobEdit @bind-Job="_job"></JobEdit>
</div>

@code
{
    private Job _job;

    protected override async Task OnInitializedAsync()
    {
        _job = await GetJob();

        await base.OnInitializedAsync();
    }

}

Ребенок:

      <EditForm Model="@_model" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />

    <div class="form-group row">
        <label class="col-xl-3 col-lg-3 col-form-label text-sm-left text-lg-right">Title</label>
        <div class="col-lg-9 col-xl-6">
            <InputText @bind-Value="_model.JobTitle" class="form-control form-control-solid form-control-lg" />
        </div>
    </div>
    <div class="form-group row">
        <label class="col-xl-3 col-lg-3 col-form-label text-sm-left text-lg-right">Department</label>
        <div class="col-lg-9 col-xl-6">
            <InputText @bind-Value="_model.Department" class="form-control form-control-solid form-control-lg" />
        </div>
    </div>
</EditForm>

@code {

    [Parameter]
    public Job Job { get; set; }

    [Parameter]
    public EventCallback<Job> JobChanged { get; set; }

    private Model _model;

    protected override async Task OnInitializedAsync()
    {
        InitializeModel();

        await base.OnInitializedAsync();
    }

    //THIS WILL UPDATE MODEL IF PARENT CHANGES
    protected override async Task OnParametersSetAsync()
    {
        InitializeModel();

        await base.OnParametersSetAsync();
    }

    private async void HandleValidSubmit()
    {
        //WE CODE HERE
        //THEN

        //THIS UPDATES PARENT IF CHILD JOB CHANGES
        await JobChanged.InvokeAsync(Job); 

        StateHasChanged();
    }

    private void InitializeModel()
    {
        _model = new Model
        {
            JobIdentifier = Job.Identifier,
            JobTitle = Job.JobTitle,
            Department = Job.Department
        };
    }

    private class Model
    {
        [Required]
        public string JobIdentifier { get; set; }

        [Required]
        public string JobTitle { get; set; }

        [Required]
        public string Department { get; set; }
    }

}
Другие вопросы по тегам