将子级与其他数据绑定

时间:2019-08-25 21:21:51

标签: blazor blazor-client-side

我正在尝试找出一些简单数据的主视图/详细视图。我有一个食谱列表,每个食谱都有一个成分列表。

我有一个“食谱”页面,其中列出了所有食谱,并且运行良好。 我有一个RecipeDetail剃刀组件,一旦从“配方”页面选择了配方,就应该获取“成分表”。

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

@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;
    }
}

以下内容在技术上是可行的,但是当我取消注释提取时,它将不再起作用。该应用程序冻结。

@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错误并仅绑定到传递的对象,但是我也找不到解决方案。我尝试了[JsonIgnore]属性,但这没有帮助。

即使Json提取是固定的,我认为我仍然有一个用例可以在参数更改后重新提取数据,因此我想了解两种情况下我做错了什么。

3 个答案:

答案 0 :(得分:0)

尝试(我尚未测试过)...

    private void sendData()
{
    if (!(btOutputStream == null)){
        try {
            btOutputStream.write("Hello".getBytes());
                ToastMaker("Data is sent");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

答案 1 :(得分:0)

为了传递组件参数,您应该在子组件中定义两个参数属性:

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

    [Parameter]
    public EventCallback<int> RecipeIdChanged { get; set; }
}

现在,无论何时在父组件中选择一个配方,从而更改了SelectedRecipeId变量的值,RecipeId参数属性的值都会更新,因此您可以通过任何方式使用新值,包括发送http请求到服务器。

在父组件中,您应该拥有这个

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

注意 <RecipeDetail @bind-RecipeId="@SelectedRecipeId"></RecipeDetail>本质上等同于写作:

<RecipeDetail @bind-RecipeId="SelectedRecipeId" @bind-RecipeId:event="RecipeIdChanged" />

注意:将值从父组件传递到子组件的另一种方法是使用AppState模式。您可以看到如何使用此模式here

您还可以使用CascadingValue组件来获得相同的功能

希望这会有所帮助

答案 2 :(得分:-1)

这是我为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}");
    }
}