1

I have a partial view (_FormCustomer) that displays a form for creating a customer. I also have a View Component (Countrylist) that generates a options list of countries. Now I want to show the country list in my form. This is what I do:

Index.cshtml

<partial name="_FormCustomer" for="@Model._Customer" />

_FormCustomer.cshtml

<select asp-for="@Model.Land" class="form-control">
    @await Component.InvokeAsync("Countrylist");
</select>

CountrylistViewComponent.cs

public async Task<IViewComponentResult> InvokeAsync()
{
    return View(await _countryRepository.GetCountriesAsync());
}

(The function GetCountriesAsync() returns a list of countries; this works fine.)

Pages/Componenst/Countrylist/default.cshtml

@model List<Country>
@foreach (Country country in Model)
{
    <option value="@country.code">@country.name</option>
}

Unfortunately, select-box stays empty when I call the partial. When I call @await Component.InvokeAsync("Countrylist"); directly from Index.cshtml, however, it works fine.

So it looks like you cannot use a View Component inside a Partial View. Is this conclusion right? Or am I doing something wrong?

1
  • Down voted as the code in the original Question text was not the same the "problem" code. In fact the code in the question text has the "correct" inclusion of the "@" symbol. Question wasted time for people trying to answer. (Original poster eventually said: "My actual code is a little different," ) Commented Feb 5, 2019 at 10:28

2 Answers 2

3

Thanks Phantom2018, found the problem after your post.

@0: I'm using Razor pages

@1: this had no effect

@2: this was a typo in my question, not in my code

@3: the debugger shows me that the vie component gets called, so

My actual code is a little different, I want to pre select a country if it's available:

<select asp-for="@Model.Country" class="form-control">
    @if (Model == null)
    {
        await Component.InvokeAsync("Countrylist");
    }
    else
    {
        await Component.InvokeAsync("Countrylist", Model.Country);
    }  
</select>

And after some testing, I found the solution:

<select asp-for="@Model.Country" class="form-control">
    @if (Model == null)
    {
        @await Component.InvokeAsync("Countrylist");
    }
    else
    {
        @await Component.InvokeAsync("Countrylist", Model.Country);
    }  
</select>

Don't know why, but I had to use @'s before the awaits.

Sign up to request clarification or add additional context in comments.

2 Comments

When I was doing my test code, I noticed that the "@" symbol was required before the await. However, I checked your question text & it did have the "@" symbol, which is why I did not mention that in my answer. Could I please request you to mark my response as the answer - as in the end it was to do with a Syntax issue (as pointed out in point 3 in my answer). (In fact with the omitted "'@" symbol, the InvokeAsync would never have been called - as I had mentioned in my response.)
This was doing my head in. My component constructor was hit, but not the render. Well spotted. +1
0

I have now tested this scenario and can confirm that the data loads fine - both, when the view component is directly included on the page or when it is included in a partial View. (I have tested this on Razor pages - but it is likely to work the same when using MVC. You have not mentioned if you are using MVC or Razor pages.)

A couple of things you can try to see if the loading works fine:

1) From all "Select"s and "Partials" remove the "for*" attributes. That way you can first check if the data loads & then you can worry about binding to the selected item. (Also, in your provided code, you have omitted the model variables - so it is not possible to comment on them.)

2) Remove the last ";" in your _FormCustomer.cshtml

<select asp-for="@Model.Land" class="form-control">
    @await Component.InvokeAsync("Countrylist")
</select>

Note that I have removed the trailing ";" in the await statement. I noticed that the ";" was added as another "option" in the select !

3) I also noticed that even minor syntax errors (not picked up by Intellisense) can cause the select to not load. Debug to see if your InvokeAsync is actually being called - in a scenario where there was a minor syntax error, the InvokeAsync was not even being called.

Also keep in mind that:

"When a partial view is instantiated, it receives a copy of the parent's ViewData dictionary. Updates made to the data within the partial view aren't persisted to the parent view. ViewData changes in a partial view are lost when the partial view returns."

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.