3

I have a @foreach loop in my Blazor page which iterates through a list of type UserInput (var userInput in UserInput).

If userInput.IsInput is false, then I will display a

with contents userInput.Text.

If userInput.IsInput is true, I will display an field and store its contents in userInputBind[index].

Below is the code I have tried:

@foreach (var userInput in myList)
{
    if (userInput.IsInput)
    {
        <input @bind="userInputBind[index]"/>
        if (index < 6) index++;
    }
    else
    {
        <p>@item.Text</p>
    }
}

@code {
    public List<UserInput> myList = new List<UserInput>
    {
        new UserInput { IsInput = false, Text = "One" },
        new UserInput { IsInput = false, Text = "Two" },
        new UserInput { IsInput = true, Text = "" },
        new UserInput { IsInput = false, Text = "Four" },
        new UserInput { IsInput = true, Text = "" },
        new UserInput { IsInput = false, Text = "Six" }
    };
    public List<string> userInputBind = new List<string> { "", "" };
    public int index;

    public class UserInput
    {
        public bool IsInput { get; set; }
        public string Text { get; set; }
    }
}

When I input "string1" into the first input field and "string2" into the second field, I expect the list to contain { "string1", "string2" }. Instead, both of the strings are "string2". How can I fix this issue? Any help is appreciated!

Ronaksse
  • 31
  • 1
  • 4
  • 1
    I suspect the global `index` field is the problem, and all bindings resolve to `userInputBind[6]`. Could you try with a `for` instead of `foreach`, and with a local variable instead of instance? – Jakub Fojtik Apr 09 '22 at 11:45
  • 1
    I recommend looking at @enet 's answer. It's one thing to figure how to do this, but the other issue is SHOULD you do it? I use this technique constantly in Blazor-- making a class with some data and a bool for Selected status. – Bennyboy1973 Apr 09 '22 at 22:16
  • Note: question edited to better fit my issue. – Ronaksse Apr 11 '22 at 13:41

1 Answers1

3

Revised Answer

I think what you're trying to do is this:

@page "/"

@{index = 0;}
@foreach (var userInput in myList)
{
    int loopindex = index;

    if (userInput.IsInput)
    {
        <input @bind="myList[loopindex].Text"/>
    }
    else
    {
        <p>@userInput.Text</p>
    }
    index++;
}

@foreach (var userInput in myList)
{
    <div class="m-2 p-2">
        Value: @userInput.Text
    </div>
}

@code {
    public List<UserInput> myList = new List<UserInput>
    {
        new UserInput { IsInput = false, Text = "One" },
        new UserInput { IsInput = false, Text = "Two" },
        new UserInput { IsInput = true, Text = "" },
        new UserInput { IsInput = false, Text = "Four" },
        new UserInput { IsInput = true, Text = "" },
        new UserInput { IsInput = false, Text = "Six" }
    };
    public int index;

    public class UserInput
    {
        public bool IsInput { get; set; }
        public string Text { get; set; }
    }
}

I don't get the purpose of:

public List<string> userInputBind = new List<string> { "", "" };

Original Answer

This works. It uses a local loop variable to capture the "index" for each loop iteration, and resets index for each render.

It may not be the solution to your problem, but it answers the question posed.

@page "/"

@{index = 0;}
@foreach (bool item in myList)
{
    if (item)
    {
        int loopindex = index;
        <div>
        <input @bind="userInputBind[loopindex]"/>
        </div>
        index++;
    }
}

@foreach(var value in userInputBind)
{
    <div class="p-2">
        Value = @value
    </div>
}

@code {
    public List<bool> myList = new List<bool> { false, false, true, false, true, false };
    public List<string> userInputBind = new List<string> { "One", "Two" };
    public int index;
}
MrC aka Shaun Curtis
  • 19,075
  • 3
  • 13
  • 31