0

I want each card I dynamically generate to have its own clickable caret to expand more details about the object.

The method I've tried so far doesn't work and doesn't throw any errors:

@foreach (Person person in people)
{
    bool showFullDetails = false;
    <div class="card">
        <div class="card-body">
            <span @onclick="()=> showFullDetails = !showFullDetails" class="@(showFullDetails ? "oi oi-chevron-down" : "oi oi-chevron-right")"></span>

            <span>@person.Type.TypeName</span>
            <span>@person.FirstName @person.LastName</span>

            @if (showFullDetails)
            {
               <div>@person.Age  - @person.Email</div>
            }
        </div>
    </div>
}

Image of an html representation of a list of people each with a clickable caret to expand for more details

GSerg
  • 76,472
  • 17
  • 159
  • 346
Jake
  • 31
  • 10
  • Does `@onclick="@(e => showFullDetails = !showFullDetails)"` work? – GSerg Aug 30 '21 at 19:25
  • Try to move the onclick to the div card-body. In case it works use a div around spans – Nicola Biada Aug 30 '21 at 20:10
  • @NicolaBiada & gserg Looks like the issue was the template defined boolean showFullDetails - every time the view is re-rendered the boolean is too – Jake Aug 30 '21 at 20:28

1 Answers1

1

You cannot define working variables in blazor like that. They must be specified in the @code section. All variables need to be predefined. Below are two examples of how you can show it.

One at a time:

<span @onclick="HideShowPerson" class="@(showFullDetails ? "oi oi-chevron-down" : "oi oi-chevron-right")"></span>


@if (ShownPerson == person)
{
    ...
}

@code {
    Person ShownPerson = null;
    
    void HideShowPerson(Person person) {
        
        // Check if person is assigned
        if (ShownPerson = person)
        {
            ShownPerson = null;
        } else {
            ShownPerson = person;
        }
    }
}

If you want to show multiple at the same time

@if (personList.Contains(person))
{
    ...
}

@code {
    // Person List
    List<Person> personList = new List<Person>();
    
    void HideShowPerson (Person person) 
    {
        if (personList.Contains(person))
        {
            personList.Remove(personList);
        } else {
            personList.Add(personList);
        }
    }
}
CorrieJanse
  • 2,374
  • 1
  • 6
  • 23
  • I added some Console.PrintLine() statements and you're 100% right. Every time the view is-rerendered aka after a click, the showDetails boolean is re-initialized to 'false'. So even though the click action is working to re-assign the variable to 'true', the whole view is then immediately re-rendered and showDetails again becomes false. – Jake Aug 30 '21 at 20:23
  • I mean absolutely no offense and thank you for providing an alternative but it feels like your suggestion of removing & adding persons to the list is a clunky work-around when I don't want to alter the list at all.. I wish there was a better blazor wasm way to achieve the dynamic show-hide – Jake Aug 30 '21 at 20:24
  • @Jake I think if you add a variable to the Person itself called visible, that can work. Other than that you can change the list you are looping through to a List<(Person person, bool visible)> and loop through that and change the visible part when approproiate. – CorrieJanse Aug 30 '21 at 20:28
  • `You cannot define working variables in blazor like that` - the [documentation](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0#lambda-expressions-1) seems to disagree. – GSerg Aug 30 '21 at 21:33
  • @GSerg, No. In the documentation it is assigning a pointer to an existing variable. In the example showed it is creating a pointer to `i` defined in the for loop. What @Jake did in the above code is define a new variable outside the code scope. If it wasn't in a @if or @for section that code would show up as text - which it should have done in the code section anyway. You can test it with the following code ` `@if (true) { int buttonNumber = 0; }`. You'll see the value never gets updated. Though it doesn't throw an error. – CorrieJanse Aug 30 '21 at 22:28
  • @user15119845 [Captures](https://stackoverflow.com/a/4158050/11683) are not pointers. I don't see a difference between `bool showFullDetails` in the OP's code that is defined outside of `@code` and the `var buttonNumber` in the [documentation example](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0#lambda-expressions-1) that is also defined outside of `@code`. – GSerg Aug 30 '21 at 23:52
  • @GSerg whatever it is, the outcome is the same. You aren't changing the value of `i`. It is static. It cannot be changed once generated by the server. And as for the example: it is defined in code -> `private string heading = "Initial heading";`, just changed by a function. Changing it outside code scope is fine, defining it outside of code scope is not fine. I've given you an example you can test for yourself. The poster couldn't get it to work (because it is not supposed to). You are just referencing docco. Just test yourself. Create a new project and try it out. You'll see it doesn't work. – CorrieJanse Aug 31 '21 at 00:00