QMarkdown extension - how to link and scroll within the markdown without reloading page



  • I’m trying to use the QMarkdown extension from https://quasarframework.github.io/quasar-ui-qmarkdown/docs to display user help information within a Quasar based help component named help.vue, which has the following characteristics:

    • Prior to introducing QMarkdown, the help information in Help.vue has been made up from HTML with embedded divs (e.g. <div id=domIdXyz>) where the ids represent scroll targets for specific help topics.

    • Help.vue uses named routes and has a property domId. In routes.js, it is declared as path: “/help/:domId”.

    • mounted: code of help.vue scrolls to the help topic in property domId using a Quasar based scroll function (which is able to do what I call “smooth” scrolling).

    • If a route change happen (e.g. to “/help/domIdXyz”), a watcher on $route(to, from) scrolls to the DOM element named “domIdXyz” to display the corresponding help topic, using the same Quasar based scroll function.

    • Within the existing template of help.vue (a mix of html for the help information and a few Quasar components), Quasar buttons (type=“to”) are used to initiate the same “smooth scrolling” within the help information through the Quasar based scroll function.

    That existing implementation works and achieves “smooth scrolling” from one element to another within the overall help information.

    Now, with having most of the help information converted to markdown content controlled by (so far one) QMarkdown component in my (changed) help template, I’m having some troubles with how to do scrolling within that markdown:

    • As far as I understand QMarkdown, I cannot embed the above Quasar buttons (type=“to” - which would be able to initiate the above “smooth scrolling”) directly into the markdown (.md file).

    • So I tried to use links <a href="/help/domIdXyz"> within the markdown to scroll to domIdXyz, but that unfortunately reloads the whole app (which after reloading the help component, scrolls to domIdXyz through the mounted: code). But reloading is not the user experience I want.

    • The same undesired reloading happens with local links in the markdown, like

    [local link](/help/domIdXYz)
    

    So I would appreciate some advise about how to get links from one topic to another topic within the markdown that scroll within the markdown without reloading the page:

    • Use links different to the above <a href=…> links/local links in the markdown?

    • Change the described routing logic to deal with it? (however, there is other code depending on it)

    • Split the markdown into many markdown files, with Quasar based buttons in between to do the linking? (seems ugly)

    Thanks for some hints.



  • @Mickey58 I will look into adding this today. You’re not the first to ask for it and can be helpful.



  • which variant of QMarkdown are you using?

    1. component
    2. md importer
    3. vmd importer


  • I think the only way this can work is if you use the VMD importer (*.vmd). This importer allows you to mix Vue and Markdown code together. Then use q-btn with to= for what you want.



  • I also found this snippet of code:

    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', function (e) {
            e.preventDefault();
    
            document.querySelector(this.getAttribute('href')).scrollIntoView({
                behavior: 'smooth'
            });
        });
    });
    

    I have added support for anchor links (as local links) to QMarkdown, so will be in next release. Then you can add code as above.





  • @Hawkeye64 - I’m using QMarkdown as a <q-markdown :src=“markdown”> component with the markdown source imported from a .md file. No use of vmd so far.



  • @Hawkeye64 - thanks for your support. I upgraded QMarkdown to the newest level 1.0.11, but have some troubles how to use the newly added anchor link support.

    I included the above code snippet as <script> … </script> within the markdown. But so far, I think it is not getting called through my tests.

    My “anchor link test” (not sure I use the anchor links in the right way though):

    1. Anchor destination within my markdown:
    <a name="anchor1">This is my anchor destination</a>
    
    1. Local anchor link within my markdown:
    [Test link to scroll to #anchor1](#anchor1)
    

    However, when clicking on that link, my whole Quasar app gets reloaded to its initial default state (which is not the help component loaded prior to clicking the link).

    This test result is worse than what I had tried before - let me call it my “local link test”:

    1. Link destination within my markdown:
    <div id="link1">This is my link destination</div>
    
    1. Local link within my markdown:
    [Test link to scroll to /help/link1](/help/link1)
    

    In this case, clicking on the link reloads the app with the help page loaded. After that, scrolling to the link1 destination happens through Quasar code in my help component. In this case, the reloading is undesired, but at least the end result is the desired one.

    So I’m not sure how to make use of the new anchor support.



  • @Mickey58 I will look into this further





  • @Hawkeye64 - I still can’t get it working. A small, but probably important difference:

    When I test the example anchor link in the new doc you provided, your examples page scrolls to: https://quasarframework.github.io/quasar-ui-qmarkdown/docs#Installation-Types - note the format “/docs#id”, not “/docs/id”.

    While in my tests, clicking on the above anchor link

    [Test link to scroll to #anchor1](#anchor1)
    

    loads http://localhost:4200/#anchor1 (which, because it is an invalid URL, leads to the mentioned reloading of my Quasar app).

    I’m testing on a local setup. Another difference is the special Vue routing logic I described in the first append above. From my existing, “pure” Quasar based version of my help component, prior to introducing QMarkdown, all my scroll destinations have the format: localhost:4200/help/id - note the “/” between"help" and “id”. As far as I remember, this is called a “named route” with the (DOM element) id as a parameter, based on a suggestion from @metalsadman. In routes.js it is specified as:

          {
            path: "/help/:helpTopicElementIdToScrollTo",
            name: "Help",
            props: true, // Vue Router "boolean mode", allows passing of helpTopicElementIdToScrollTo to the component, which has that id defined as a prop
            component: () => import("pages/Help.vue")
          },
    

    So one possible solution would be to change my routing setup to accomodate this “/help#id” rather than"/help/id" - but I don’t know how to do that.



  • Small update: I did a sniff test in which I temporarily disabled the mentioned named route for my help component, both in its definition in Vue routes, and in the surrounding <q-route-tab> of MyLayout.vue:

    With this modified setup, the anchor links within the markdown, if specified as “/help#anchor1”, scroll to the anchor destination. This proves that in my case there is some conflict between the use of named routes and those anchors.

    But I cannot easily get rid of the named routes in general, as I have a table of content in the left drawer that depends on it. I would have to convert that to anchor links somehow as well, but I’m neither sure whether that is possible nor how to do that.

    There is an additional glitch, that the scrolling to an anchor link (with named route disabled) always scrolls a few lines too far, not sure what is causing that additional small problem.



  • The scrolling is done by the browser. If you have a header of any sorts, then it won’t take that into account as it is relative to the top of the view.

    If you want to anchor link to the same page, don’t put a path in front, otherwise the browser will reload. #the-id assumes it is on same page and will not cause a reload.



  • Ok, the header (in MyLayout.vue) explains the offset when scrolling. Do you have an idea how to achieve a scroll within the page that compensates for that offset? Could I embed a special scroll function into the markdown part for that, like the code snippet you mentioned in an earlier post above?

    I have tried anchor links without path in front. For some reason, with my “named route with prop” setup,for Help.vue a local link without path, like

    [Test link to scroll to #anchor1](#anchor1)
    

    reloads the app to a default state outside of the help component, without scrolling to anywhere (FAIL).

    Even with the “named route with prop” setup for my help component temporarily disabled, the same local link to #anchor1 reloads the app as well (FAIL)!

    Also with the “named route with prop” route setup disabled,

    [Test link to scroll to /help#anchor1](/help#anchor1)
    

    performs the desired scrolling (PASS - with the mentioned offset though).


Log in to reply