绑定 child 与额外的数据获取

Binding child with additional data fetch

我正在尝试找出一些简单数据的 master/detail 视图。我有一份食谱清单,每个食谱都有一份配料清单。

我有一个列出所有食谱的食谱页面,而且效果很好。 我有一个 RecipeDetail 剃刀组件,一旦从“食谱”页面选择了一个食谱,它就应该获取成分列表。

我试过各种各样的东西。我已经尝试通过将 Recipe 及其成分完全填充到 RecipeDetail 组件来进行数据绑定,但是由于数据结构,GetJsonAsync 方法检测到循环引用并引发异常。我已经尝试通过绑定到食谱页面上的变量的参数将从食谱页面选择的食谱的 ID 向下传递到 RecipeDetail 页面,但从未触发数据获取。

@page "/recipes"
@using BlazorApp.Shared.Models
@inject HttpClient Http

<h1>Recipes</h1>

@if(RecipesArray != null)
{
    @foreach (var r in RecipesArray)
    {
        <h3 @onclick="@(() => SelectRecipe(r))">@r.Title</h3>
    }
}

<RecipeDetail RecipeId="@SelectedRecipeId"></RecipeDetail>

@code {
    Recipe[] RecipesArray;
    int SelectedRecipeId;

    protected override async Task OnInitializedAsync()
    {
        RecipesArray = await Http.GetJsonAsync<Recipe[]>("Recipes");
    }

    protected void SelectRecipe(Recipe recipe)
    {
        SelectedRecipeId = recipe.Id;
    }
}

下面的技术在技术上有效,但当我 un-comment 获取时,它不再有效。应用程序冻结。

@using BlazorApp.Shared.Models
@inject HttpClient Http

<h1>RecipeId = @selectedRecipeId</h1>
@if (Ingredients != null && Ingredients.Length > 0)
{
    <h1>@RecipeId</h1>
    <ul>
        @foreach (var item in Ingredients)
        {
            <li>@item.Ingredient.ToString()</li>
        }
    </ul>
}


@code {
    private int selectedRecipeId;
    RecipeIngredient[] Ingredients;

    [Parameter]
    public int RecipeId
    {
        get { return selectedRecipeId; }
        set
        {
            selectedRecipeId = value;
            //if (value > 0)
            //    Ingredients = Http.GetJsonAsync<RecipeIngredient[]>($"Recipes/{RecipeId}").Result;
        }
    }
}

我很乐意修复 JSON 错误并绑定到传下来的 object,但我也找不到解决方案。我尝试了 [JsonIgnore] 属性,但这没有帮助。

即使 Json 获取已修复,我想在参数更改后我仍然有 re-fetch 数据的用例,所以我想了解我做错了什么在这两种情况下。

试试(我还没有测试过)...

@page "/recipes"
@using BlazorApp.Shared.Models
@inject HttpClient Http

<h1>Recipes</h1>

@if(RecipesArray != null)
{
    @foreach (var r in RecipesArray)
    {
        <h3 @onclick="@(() => SelectRecipe(r))">@r.Title</h3>
    }
}

<RecipeDetail RecipeId="@SelectedRecipeId" Ingredients="@Ingredients"></RecipeDetail>

@code {
    Recipe[] RecipesArray;
    int SelectedRecipeId;
    RecipeIngredient[] Ingredients = new RecipeIngredient[]();

    protected override async Task OnInitializedAsync()
    {
        RecipesArray = await Http.GetJsonAsync<Recipe[]>("Recipes");
    }

    protected void SelectRecipe(Recipe recipe)
    {
        SelectedRecipeId = recipe.Id;
        if (value > 0)
        {
          Ingredients = Http.GetJsonAsync<RecipeIngredient[]>($"Recipes/{SelectedRecipeId}").Result;
        }
    }
}

and:

<h1>RecipeId = @selectedRecipeId</h1>
@if (Ingredients != null && Ingredients.Length > 0)
{
    <h1>@RecipeId</h1>
    <ul>
        @foreach (var item in Ingredients)
        {
            <li>@item.Ingredient.ToString()</li>
        }
    </ul>
}


@code {
    [Parameter]
    public int RecipeId;

    [Parameter]
    public RecipeIngredient[] Ingredients;
}

这是我为 RecipeDetail 想出的解决方案

@using BlazorApp.Shared.Models
@inject HttpClient Http

@if (Ingredients != null && Ingredients.Length > 0)
{
    <ul>
        @foreach (var item in Ingredients)
        {
            <li>@item.ToString()</li>
        }
    </ul>
}


@code {
    RecipeIngredient[] Ingredients;

    [Parameter]
    public int RecipeId { get; set; }

    protected override async Task OnParametersSetAsync()
    {
        if (RecipeId != 0)
        {
            await LoadRecipeDetails(RecipeId);
        }
    }

    private async Task LoadRecipeDetails(int RecipeId)
    {
        Ingredients = await Http.GetJsonAsync<RecipeIngredient[]>($"Recipes/{RecipeId}");
    }
}