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

Markdown element is not updated if it is not displayed (for example in tooltip or tab_panel) #2779

Closed
me21 opened this issue Mar 28, 2024 · 12 comments · Fixed by #2803
Closed
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@me21
Copy link
Contributor

me21 commented Mar 28, 2024

Description

I'd like to use a textarea to edit Markdown and to display Markdown content in a tooltip:

with ui.textarea('Instructions') as textarea:
    with ui.tooltip():
        markdown = ui.markdown()
        textarea.bind_value_to(markdown, 'content', lambda t: t or '')  # doesn't like None as content

It mostly works, but the tooltip content is lost if I move the mouse out of textarea and then back. The empty tooltip appears, but after editing the textarea, its contents are updated properly.

@falkoschindler
Copy link
Contributor

Thanks for reporting this issue, @me21!

That's very strange. It works for labels and HTML, but not for Markdown elements:

with ui.textarea() as textarea:
    with ui.tooltip():
        ui.label().bind_text_from(textarea, 'value')
        ui.html().bind_content_from(textarea, 'value')
        ui.markdown().bind_content_from(textarea, 'value')

I guess the update method in markdown.js can't render the new content while the tooltip element isn't visible. Here is another example using tabs:

textarea = ui.textarea()
with ui.tabs() as tabs:
    one = ui.tab('One')
    two = ui.tab('Two')
with ui.tab_panels(tabs, value=one):
    with ui.tab_panel(one):
        ui.label('First tab')
    with ui.tab_panel(two):
        ui.label('Second tab')
        ui.markdown().bind_content_from(textarea, 'value')

Before visiting the second tab for the first time, the Markdown element doesn't receive any updates. This is similar to issue #1869 which has been resolved by re-implementing ui.log.

At the moment I'm not sure how to solve this problem for ui.markdown. Any help is greatly appreciated.

@falkoschindler falkoschindler added bug Something isn't working help wanted Extra attention is needed labels Mar 29, 2024
@falkoschindler falkoschindler changed the title Tooltip contents are not preserved Markdown element inside tooltip is not updated Mar 29, 2024
@rodja rodja changed the title Markdown element inside tooltip is not updated Markdown element is not updated if it is not displayed (for example in tooltip or tab_panel) Mar 30, 2024
@aniketkumar7
Copy link

Is it works if we could use the on_hover and on_leave events of the textarea to update the tooltip's content.

@me21
Copy link
Contributor Author

me21 commented Apr 2, 2024

How is ui.markdown translated to the client side? If I understand correctly, ui.html has no such issues, but ui.markdown is rendered to html, so it should behave the same, but it doesn't.
Maybe make it a subclass of ui.html? 🤔

@aniketkumar7
Copy link

The ui.markdown function in the ui library is translated to the client side using the marked library, which is a JavaScript library for rendering Markdown to HTML.

While making ui.markdown a subclass of ui.html could be an interesting idea, it’s essential to understand their fundamental differences:
ui.html directly renders HTML content.
ui.markdown converts Markdown to HTML before rendering.
, but it would require significant changes to the ui library.

@falkoschindler
Copy link
Contributor

@aniketkumar7 Exactly. Here is the code that runs mermaid.run:

update(content) {
this.$el.innerHTML = content;
this.$el.querySelectorAll(".mermaid-pre").forEach(async (pre, i) => {
await this.mermaid.run({ nodes: [pre.children[0]] });
});
},

@falkoschindler
Copy link
Contributor

Oh wait, my last comment confused Markdown with Mermaid. A plain ui.markdown element without Mermaid diagrams should indeed behave very similar to ui.html... 🤔

@falkoschindler
Copy link
Contributor

I think the fundamental problem is that the QTooltip element gets created every time the text area is hovered, while the ui.tooltip element on the server persists the whole time. This way the QTooltip on the client doesn't get updates when they occur, because it doesn't exist at that time. I've still no clue what to do about it.

@me21
Copy link
Contributor Author

me21 commented Apr 2, 2024

@falkoschindler But why ui.html nested into ui.tooltip doesn't have this problem?
If I understand correctly, markdown is rendered to html at the server?

@me21
Copy link
Contributor Author

me21 commented Apr 2, 2024

I rewritten the ui.markdown class as a subclass of ui.html:

class MyMarkdown(ui.html):
    def __init__(self, content: str = '', *, extras: List[str] = ['fenced-code-blocks', 'tables']) -> None:
        """Markdown Element

        Renders Markdown onto the page.

        :param content: the Markdown content to be displayed
        :param extras: list of `markdown2 extensions <https://github.com/trentm/python-markdown2/wiki/Extras#implemented-extras>`_ (default: `['fenced-code-blocks', 'tables']`)
        """
        self.extras = extras
        super().__init__(content=content)
        self._classes.append('nicegui-markdown')
        self._props['codehilite_css'] = (
            HtmlFormatter(nobackground=True).get_style_defs('.codehilite') +
            HtmlFormatter(nobackground=True, style='github-dark').get_style_defs('.body--dark .codehilite')
        )
        if 'mermaid' in extras:
            self._props['use_mermaid'] = True
            self.libraries.append(Mermaid.exposed_libraries[0])

    def _handle_content_change(self, content: str) -> None:
        html = prepare_content(content, extras=' '.join(self.extras))
        super()._handle_content_change(html)

Seems to work. Please feel free to test.

@me21
Copy link
Contributor Author

me21 commented Apr 2, 2024

I realized that by omitting the reference to markdown.js file I might have broken the interaction with Mermaid and Codehilite.
I think it can be fixed by referencing that file again, and removing this.$el.innerHTML = content; line from update(content) method, but I'm not sure.

I will prepare a PR but how do I test that Mermaid and Codehilite work correctly?

@me21
Copy link
Contributor Author

me21 commented Apr 2, 2024

In this PR, markdown.js file is still referenced in the markdown component, but Mermaid diagrams inside Markdown are now broken, not sure why. On another hand, markdown now updates correctly if tooltip is hidden.

@me21
Copy link
Contributor Author

me21 commented Apr 2, 2024

Mermaid diagrams work now. Please test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants