Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui.refreshable updating the wrong element #1283

Closed
falkoschindler opened this issue Jul 28, 2023 · 2 comments · Fixed by #1313
Closed

ui.refreshable updating the wrong element #1283

falkoschindler opened this issue Jul 28, 2023 · 2 comments · Fixed by #1313
Assignees
Labels
bug Something isn't working
Milestone

Comments

@falkoschindler
Copy link
Contributor

falkoschindler commented Jul 28, 2023

Description

This observation originates from a StackOverflow question: https://stackoverflow.com/questions/76763206/is-it-possible-to-use-widgets-in-nicegui-python

The following code creates two refreshable buttons, each of which refreshes itself and notifies the user about it. But independent of which button is clicked, it always refreshes button B.

class Test:

    def __init__(self, name):
        self.name = name
        self.ui()

    @ui.refreshable
    def ui(self):
        ui.notify(f'Refreshing {self.name}')
        ui.button(self.name, on_click=self.ui.refresh)

Test('A')
Test('B')

The problem can be avoided by replacing

on_click=self.ui.refresh

with

on_click=lambda: self.ui.refresh()

But what is the reason for this mixup, and how to fix it?

@falkoschindler falkoschindler added bug Something isn't working help wanted Extra attention is needed labels Jul 28, 2023
@falkoschindler
Copy link
Contributor Author

I think I understand:

self.ui is static. By overriding the __get__ method, we keep track of the instance that is supposed to be used for the refresh() call.

But if we set the click handler directly like on_click=self.ui.refresh, the __get__ method isn't called when clicking the button and the last instance is used.

If we wrap the click handler in a lambda function like on_click=lambda: self.ui.refresh(), the __get__ method is called as part of the lambda function and correct instance is set before executing the refresh function.

I just don't know how to fix this bug.

@falkoschindler
Copy link
Contributor Author

I found something:

    def __getattribute__(self, __name: str) -> Any:
        if __name == 'refresh':
            def refresh(instance=self.instance, *args: Any, **kwargs: Any) -> None:
                self.instance = instance
                object.__getattribute__(self, __name)(*args, **kwargs)
            return refresh
        return object.__getattribute__(self, __name)

This fixes the bug, but is still work in progress.

@falkoschindler falkoschindler self-assigned this Aug 2, 2023
@falkoschindler falkoschindler added this to the 1.3.7 milestone Aug 2, 2023
@falkoschindler falkoschindler removed the help wanted Extra attention is needed label Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant