MatBlazor icon indicating copy to clipboard operation
MatBlazor copied to clipboard

Cannot read property 'classList'

Open gratiaterra opened this issue 5 years ago • 10 comments
trafficstars

Describe the bug Click a MatButton that removes an item from a list bound in MatSelect, then sets a selected index on MatSelect to a valid index in the list. Page load crashes

To Reproduce <MatButton OnClick="@Delete" Icon="delete">Yes, remove item</MatButton>

async Task Delete() { matSelectedList.Remove(selectedItem); selectedItem=matSelectedList.FirstOrDefault(); StateHasChanged(); //crash }

This was not seen until a recent update to latest nuget.

** Crash: Microsoft.JSInterop.JSException: Cannot read property 'classList' of undefined blazor.webassembly.js:1 TypeError: Cannot read property 'classList' of undefined blazor.webassembly.js:1 at Object.removeClassAtIndex (http://localhost:53414/_content/MatBlazor/dist/matBlazor.js:1:207672) blazor.webassembly.js:1 at e.setSelectedIndex (http://localhost:53414/_content/MatBlazor/dist/matBlazor.js:1:62195) blazor.webassembly.js:1 at e.setValue (http://localhost:53414/_content/MatBlazor/dist/matBlazor.js:1:62679) blazor.webassembly.js:1 at e.set [as value] (http://localhost:53414/_content/MatBlazor/dist/matBlazor.js:1:204199) blazor.webassembly.js:1 at Object.e.setValue (http://localhost:53414/_content/MatBlazor/dist/matBlazor.js:1:199107) blazor.webassembly.js:1 at http://localhost:53414/_framework/blazor.webassembly.js:1:9805 blazor.webassembly.js:1 at new Promise () blazor.webassembly.js:1 at Object.beginInvokeJSFromDotNet (http://localhost:53414/_framework/blazor.webassembly.js:1:9773) blazor.webassembly.js:1 at _mono_wasm_invoke_js_marshalled (http://localhost:53414/_framework/wasm/dotnet.3.2.0.js:1:171294) blazor.webassembly.js:1 at do_icall (:wasm-function[6049]:0x10f8b1) blazor.webassembly.js:1 at System.Threading.Tasks.ValueTask`1[TResult].get_Result () <0x42e1888 + 0x0002c> in :0 blazor.webassembly.js:1 at MatBlazor.BaseMatComponent.JsInvokeAsync[T] (System.String code, System.Object[] args) <0x47ea1b8 + 0x000d6> in :0

gratiaterra avatar Jul 19 '20 17:07 gratiaterra

I am experiencing the same issue, the error happens when you change both the binded value and the item list. As a workaround you have to call twice StateHasChanged, first change the binded value, call StateHasChanged, then update the item list and recall StateHasChanged.

fededim avatar Sep 24 '20 11:09 fededim

I've not had time yet to do anything with this except confirm it is an issue (I found the issue when another one of my dev co-workers was asking why the select wasn't working).

@fededim or @gratiaterra , are either of y'all interested in doing the work to resolve this one?

Christian-Oleson avatar Oct 12 '20 18:10 Christian-Oleson

@enkodellc , is it possible to get a label on this one (and other tickets) where we have confirmed the issue exists?

Christian-Oleson avatar Oct 12 '20 18:10 Christian-Oleson

@Christian-Oleson "bug" is there so in my opinion if you come across something that is not a bug then I would change it to something different. Just my 2 cents, use what is there instead creating more labels.

enkodellc avatar Oct 13 '20 06:10 enkodellc

Found this bug today while using MatSelectValue too.

Tried calling StateHasChanged(); twice as suggested above, but still got error anyway, so workaround hasn't worked for me.

Edit: Apparently, error only happens when previously selected index was not zero. If it was zero, it works fine

naretto avatar Oct 29 '20 00:10 naretto

Opened a duplicate of this issue. But transferring my workaround here and closing my Issue.

Workaround done by compiling js from Github source and using this JS file instead of the one bundles in the NuGet, then adding null check

removeClassAtIndex: function (e, n) {
    if (t.menu.items[e] != null && t.menu.items[e].classList != null) {
        t.menu.items[e].classList.remove(n);
    }
}

as well as

setAttributeAtIndex: function (e, n, i) {
    if (t.menu.items[e] != null) {
         t.menu.items[e].setAttribute(n, i);
    }
}

dorana avatar Nov 15 '20 23:11 dorana

Opened a duplicate of this issue. But transferring my workaround here and closing my Issue.

Workaround done by compiling js from Github source and using this JS file instead of the one bundles in the NuGet, then adding null check

removeClassAtIndex: function (e, n) {
    if (t.menu.items[e] != null && t.menu.items[e].classList != null) {
        t.menu.items[e].classList.remove(n);
    }
}

as well as

setAttributeAtIndex: function (e, n, i) {
    if (t.menu.items[e] != null) {
         t.menu.items[e].setAttribute(n, i);
    }
}

Would you be able to open a PR to fix this in the next release? That would be helpful!

Christian-Oleson avatar Nov 16 '20 16:11 Christian-Oleson

I finally had some time to look into this today and it is not as easy to fix.

I looked into the MatSelect code, looking for those JavaScript functions and could not find them (other than in the minified JS file).

MatSelect is only wrapping the MDC Select component from Material itself and those functions come from there:

  • https://github.com/material-components/material-components-web/blob/a3212b2099765947f2a41d71af2cd95fcbca4b97/packages/mdc-select/component.ts#L382
  • https://github.com/material-components/material-components-web/blob/a3212b2099765947f2a41d71af2cd95fcbca4b97/packages/mdc-select/component.ts#L400

The wrapping targets material version 7.0.0, which has those functions. However, material has now moved to version 8.0.0 and those functions were entirely removed.

That is listed under the breaking changes: https://github.com/material-components/material-components-web/blob/v8.0.0/CHANGELOG.md

So long story short the bug originates from a dependency and that dependency has moved on. We could fix the minified JS in MatBlazor, but that's not a proper solution as any time the file is regenerated, the fix would be lost.

I think for now, I will do the same as suggested by dorana and just fix my JS file and point to it instead of package one.

Maybe there is a better solution, like override the methods coming from the dependency. Not sure (maybe MatBlazor will move to Material 8 so this becomes a nonissue?).

Edit: Yes, it seems the packages from material will be updated to version 8 in the future: https://github.com/SamProf/MatBlazor/commit/9a35f3eadebd34c71395ee48b8421b600a8b6d44

So this will need retesting after this version is out and this bug may or may not still be around.

naretto avatar Nov 23 '20 01:11 naretto

I will update MatBlazor to latest MDC 10.0 in very nearest time.

SamProf avatar Mar 07 '21 22:03 SamProf

If your MatSelect's are generated by some loop, I managed to fix it by applying the @key="selectedItem" parameter to the looped component which has the MatSelect.

RoelHermans avatar Apr 28 '21 15:04 RoelHermans