Odd Behavior seems to be related to Async Javascript Call

Posted 3 years ago by Andreas
0

Hello Everyone,

I have a complex Table in my .NET 5 Webassembly App. It has a dynamic Search with 2 Searchboxes, that adapt the table dynamically on keystroke, when a field contains the results of the keystrokes. One can dynamically select an icon per tableentry which will then dynamically load a small subtable with rows that only this specific entry has. Works all great so far. 

I use reflections to accomplish this which works great.

in My last feature update I wanted to add the Searchtext of the Searchtext Boxes to my subtable and highlight it in there so the user can see why this row was chosen. It also works, used I async Javascript call to accomplish this setting innerHtml via Javascript.

export function SetInnerHtml(id, innerhtmlstring) {
    var element = document.getElementById(id);
    if (element != null) {
        element.innerHTML = innerhtmlstring;
    }
}

I then get this odd message in my dyanamic subtable filled up by: @PropValueSetInnerHtml(). No error is thrown, cannot find this message anywhere seems to be related to the async javascript calls. Before calling javascript and feeding the method all values are set right.

I have added login in order to get to the bottom since debugging seems to still have a view issues (Hope that adding complex watches in debug will work soon, also fullpage formating would be great :)). 

Wired Message: System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Threading.Tasks.VoidTaskResult,xxx.Client.Pages.Resources+<PropValueSetInnerHtml>d__59]
//My Page Code:
...
        <tbody>
               @foreach (var item in FilteredItems)
                {
                	...
                    <td data-toggle="tooltip" title="Title of Entry">@item.Title</td>
                    ...
                    <td><input @onclick="@(e => SetToEditMode(@item, ResourceType.Misc))" type="image" src="images/Misc.png" data-toggle="tooltip" title="Different Detail Information"/></td>
                    ...
                	else if (!IsMobile && IsInEditMode && CurrentId == item.Id && CurrentResourceType == ResourceType.Misc)
						{
                            ...
                            for (CurrenFieldtId = 0; CurrenFieldtId < Fields.Count; CurrenFieldtId++)
                            {
                                ...
                                PropValue = FilteredItems.First(n => n.Id == CurrentId).GetPropValue(Fields[CurrenFieldtId].PropertyName);
                                if(!PropValue.IsNullOrEmpty())
                                {
									...
                                    if (CurrenFieldtId == 0)
                                    {
                                        <tr class="extenderheader">
                                            <td colspan=1>
                                                <input @onclick="@(e => RemoveEditMode(@item.Id))" type="image" src="images/Close.png" data-toggle="tooltip" title="Close"/>
                                            </td>
                                            <td colspan=11 style="text-align:center;">@Fields[CurrenFieldtId].DisplayName</td>
                                        </tr>
                                    }
                                    else
                                    {
                                        <tr class="extenderheader">
                                            <td colspan=1>
                                            </td>
                                            <td colspan=11 style="text-align:center;">@Fields[CurrenFieldtId].DisplayName</td>
                                        </tr>
                                    }
                                    <tr class="extender">
                                        <td id="@PropValueCurrentId" colspan=12 style="text-align:center;">@PropValueSetInnerHtml()</td>
                                    </tr>
                                }
                            }
                        }
                }
        </tbody>
...
}
@code {
    private List<Field> Fields { get; set; } = new List<Field>() 
    { 
        new Field{PropertyName = "Summary", DisplayName= "Summary"} , 
        new Field{PropertyName = "PhysicalLocation", DisplayName= "Physical Location"},
        new Field{PropertyName = "Cast", DisplayName= "Cast"},
        new Field{PropertyName = "Directors", DisplayName= "Directors"},
        new Field{PropertyName = "Genre", DisplayName= "Genre"}
    };
    private IJSObjectReference JsModule { get; set; }   
    private int FilteredItemsCurrentId { get; set; }
    private int FilteredItemsIndex { get; set; }
    private int CurrentId { get; set; }
    private int CurrenFieldtId { get; set; }
    private string PropValueCurrentId { get { return "Prop" + CurrenFieldtId; } }
    private object PropValue { get; set; }
    private bool IsInEditMode { get; set; } = false;
    private string SearchTerm1 { get; set; } = "";
    private string SearchTerm2 { get; set; } = "";
    private List<Resource> resources = null;
    private bool IsMobile { get; set; }
    protected override async Task OnInitializedAsync()
    {
        JsModule = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./common.js");
        IsMobile = await JsModule.InvokeAsync<bool>("IsMobile");
        resources = await Http.GetFromJsonAsync<List<Resource>>("Resource");   
    }
    List<Resource> FilteredItems => resources.Where(n =>
    {
        return (new List<string> { n.Title, n.Summary, n.Teacher, n.Author, n.ConferenceName, n.Subtitle, n.Cast, n.Directors, n.Genre }).ContainsItems(new List<string> { SearchTerm1, SearchTerm2 });
    }).ToList();
    private async Task PropValueSetInnerHtml()
    {
        if (PropValue.ToString().ToLowerAndContains(SearchTerm1.ToLower()) && PropValue.ToString().ToLowerAndContains(SearchTerm2.ToLower()))
        {
            await JsModule.InvokeVoidAsync("SetInnerHtml", PropValueCurrentId, PropValue.ToString().ReplaceCaseInsensitive(SearchTerm1, "<b style=\"background-color:yellow;\">" + SearchTerm1 + "</b>").ReplaceCaseInsensitive(SearchTerm2, "<b style=\"background-color:orange;\">" + SearchTerm2 + "</b>"));
        }
        else if (PropValue.ToString().ToLowerAndContains(SearchTerm1.ToLower()) && !PropValue.ToString().ToLowerAndContains(SearchTerm2.ToLower()))
        {
            await JsModule.InvokeVoidAsync("SetInnerHtml", PropValueCurrentId, PropValue.ToString().ReplaceCaseInsensitive(SearchTerm1, "<b style=\"background-color:yellow;\">" + SearchTerm1 + "</b>"));
        }
        else if (!PropValue.ToString().ToLowerAndContains(SearchTerm1.ToLower()) && PropValue.ToString().ToLowerAndContains(SearchTerm2.ToLower()))
        {
            await JsModule.InvokeVoidAsync("SetInnerHtml", PropValueCurrentId, PropValue.ToString().ReplaceCaseInsensitive(SearchTerm2, "<b style=\"background-color:yellow;\">" + SearchTerm2 + "</b>"));
        }
        else
        {
            await JsModule.InvokeVoidAsync("SetInnerHtml", "propvalueid", PropValue.ToString());
        }
    }
    private async Task SetToEditMode(Resource item, ResourceType resourcetype)
    {
        var oldvalue = CurrentId.ToString();
        IsInEditMode = true;
        CurrentId = item.Id;
        CurrentResourceType = resourcetype;
        await JsModule.InvokeVoidAsync("RemoveTrBackgroundColor", oldvalue);
        await JsModule.InvokeVoidAsync("SetTrBackgroundColor", CurrentId, "background-color: lightgreen;");
    }
}

I found out what I do not understand really:

I click Row Detail Button:
@onclick="@(e => SetToEditMode(@item, ResourceType.Misc))"

Once CurrentId is set,
private async Task SetToEditMode(Resource item, ResourceType resourcetype)
    {
        ...
        CurrentId = item.Id;
        ...
which is bound to this code section for my dynamic subtable (else if (!IsMobile && IsInEditMode && CurrentId == item.Id && CurrentResourceType == ResourceType.Misc))
This code section "Awakes", it has never been executed before. The CurrentId Propertychange seems to awake it.

Then what I really do not understand next the code jumps to "@foreach (var item in FilteredItems)" at the beginning and then enters the if case which is now open.

Sorry if my explanation is unclear.

My two Questions are:
1) Why do I get this odd Message instead of the real value in my table set through Javascript innerhtml?
2) Why does the Code awake on a property change and then jump to the very beginning of the loop itterating throw all its items and only then enter the open if case?

Any Help will be GREATLY appreciated.
LOVE Blazor once I understand it better. Thanks a lot Kind blessings, Andreas

 

 

 

 

  • 0

    I believe the main issue may be that PropValueSetInnerHtml() is returning a Task, since it isn't awaited.

    Posted 3 years ago by selliott
  • 0

    Thanks a lot for your answer!

    Passed in the wrong html element id so it could not set the text in one case :)

    This line was the problem, thx!

    Posted 3 years ago by Andreas
Someone is typing...

Post a Reply

You must be logged in to add a new post.
Number of online users: 0
An error has occurred. This application may no longer respond until reloaded. Reload 🗙