1

The “@ref” refers to the current element that is correct.

“@ref” refers to the last element in loop command that is not correct (in my example, the last tr element of the table element).

I want that “@ref” refers to per element individually (in my example, per tr element of the table element) not to the last element.

@inject IJSRuntime JsRuntime;

<table class="table">
    <tbody>
        @foreach (var item in Items)
        {
            <tr @ref="@row" @onclick="() => {Rowclick(row);}">
                <td>@item</td>
            </tr>
        }
    </tbody>
</table>

@code
{
    public string[] Items = new string[] { "Tomas", "Jack", "Michael" };

    public async void Rowclick(ElementReference row)
    {
        await JsRuntime.InvokeAsync<object>("updateBackgroundColor", row);
    }
}

//--------------------------

<script type="text/javascript">
    function updateBackgroundColor(row) {
        row.bgColor = 'red';
    }
</script>
Alireza
  • 170
  • 4
  • 17
  • 1
    If you want to workaround, you can pass the **index of item as id of tr tag**. And in js you get element by that id. (Haha) – Phat Huynh Sep 23 '19 at 10:51
  • 4
    Related Question: [Blazor MatMenu taken last value in all menu in foreach loop](https://stackoverflow.com/questions/57283973/blazor-matmenu-taken-last-value-in-all-menu-in-foreach-loop) - To summarise, you need a unique reference in each iteration, instead of reusing `@row` (What is `@row` and where does it come from anyway?) – A Friend Sep 23 '19 at 10:54
  • Thanks but I want to use @@ref @phat.huynh – Alireza Sep 23 '19 at 11:12
  • Please answer to my question here @AFriend – Alireza Sep 23 '19 at 11:15
  • 3
    I think you misunderstood the point of my comment. The linked question has a similar issue which may help to address the problem described here. It isn't to steal focus away from your question – A Friend Sep 23 '19 at 15:21
  • I appreciate you taking time @AFriend – Alireza Sep 24 '19 at 07:17

2 Answers2

3

This is your answer:

    @using Microsoft.AspNetCore.Components;
    @inject IJSRuntime JsRuntime;

    <table class="table">
    <tbody>
        @foreach (var item in Items)
        {
            <tr @ref:suppressField @ref="@item.Row" @onclick="@(() => {ClickForTestRow(item.Row);})">
                <td>@item.Name</td>
            </tr>
        }
    </tbody>
    </table>


@code {
[Parameter]
public IList<MyModel> Items { get; set; }

public async void ClickForTestRow(ElementReference row)
{
    await JsRuntime.InvokeAsync<object>("updateBackgroundColor", row, "red");
}

public class MyModel
{
    public ElementReference Row { get; set; }

    public string Name { get; set; }
}
}

//----------------

<script type="text/javascript">
    function updateBackgroundColor(row) {
        row.bgColor = 'red';
    }
</script>
ali
  • 46
  • 2
  • As of writing this `@ref:suppressField` is not needed as it is not available anymore. Seems like you always have to define a backing field hence not automatic backing field generation needs to be suppressed. – ViRuSTriNiTy Mar 16 '20 at 20:54
  • Adding an ElementReference in a model... That goes against everything the model pattern stands for... Namely separation of concerns. You've mixed your presentation layer and your data layer together in your model. – sw1337 Sep 03 '20 at 02:17
  • 2
    @sw1337 how do you know it's not his viewmodel? – Jesper Oct 11 '20 at 08:11
1

Try something like this. I did not tried out the js part.

@for (int i = 0; i < Items.Length; i++)
{
    <p @ref="Refs[i]">@Items[i]</p>
}

@code {
    public string[] Items = new string[] { "Tomas", "Jack", "Michael" };
    ElementReference[] Refs = new ElementReference[4];
}
Zsolt Bendes
  • 2,219
  • 12
  • 18
  • this is bad. @ref behaves like a lambda, so the `i` needs to be captured locally, otherwise its the same error as OP mentions. Im still looking for a way for VARIABLE LENGTHs, this only works for fixed sized arrays. See: https://stackoverflow.com/questions/58205090/using-ref-inside-for-loop-to-get-element-reference – somedotnetguy Aug 15 '22 at 17:39