Anchor links support

Hello everyone,

In our jmix application, we created a static page with a Help content. Inside this page we would like to use HTML anchors in order better navigate inside the page.

Is there any way in jmix to have an anchor links?

Thank you in advance for any ideas and suggestions!

Hi,

Unfortunately, anchors cannot be added easily because the framework handles all url changes and treats # as a special symbol, e.g. #main, #login. But, you can implement custom anchor functionality using URL History and Navigation API and URL query parameters.

Below my simple help page implementation

<layout>
    <vbox spacing="true">
        <linkButton id="firstParagraph" caption="First Paragraph"/>
        <label value="msg://loremIpsum" width="500px"/>

        <linkButton id="secondParagraph" caption="Second Paragraph"/>
        <label value="msg://loremIpsum" width="500px"/>

        <linkButton id="thirdParagraph" caption="Third Paragraph"/>
        <label value="msg://loremIpsum" width="500px"/>
    </vbox>
</layout>
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import io.jmix.ui.component.Button;
import io.jmix.ui.component.Component;
import io.jmix.ui.component.LinkButton;
import io.jmix.ui.navigation.Route;
import io.jmix.ui.navigation.UrlParamsChangedEvent;
import io.jmix.ui.navigation.UrlRouting;
import io.jmix.ui.screen.Screen;
import io.jmix.ui.screen.Subscribe;
import io.jmix.ui.screen.UiController;
import io.jmix.ui.screen.UiDescriptor;
import org.springframework.beans.factory.annotation.Autowired;

@UiController("Sandbox")
@UiDescriptor("sandbox.xml")
@Route("sandbox")
public class Sandbox extends Screen {

    @Autowired
    private LinkButton firstParagraph;
    @Autowired
    private LinkButton secondParagraph;
    @Autowired
    private LinkButton thirdParagraph;

    @Autowired
    private UrlRouting urlRouting;

    @Subscribe
    public void onInit(InitEvent event) {
        firstParagraph.addClickListener(this::onAnchorClick);
        secondParagraph.addClickListener(this::onAnchorClick);
        thirdParagraph.addClickListener(this::onAnchorClick);
    }

    public void onAnchorClick(Button.ClickEvent event) {
        String anchorId = event.getSource().getId();
        if (!Strings.isNullOrEmpty(anchorId)) {
            urlRouting.replaceState(this, ImmutableMap.of("anchor", anchorId));
        }
    }

    @Subscribe
    public void onUrlParamsChanged(UrlParamsChangedEvent event) {
        String anchorId = event.getParams().get("anchor");
        if (!Strings.isNullOrEmpty(anchorId)) {
            Component anchor = getWindow().getComponent(anchorId);
            if (anchor instanceof Component.Focusable) {
                ((Component.Focusable) anchor).focus();
            }
        }
    }
}

The idea is that anchors are clickable components, e.g. LinkButton. When such anchor is clicked the URL query params are updated, e.g.: http://localhost:8080/#main/0/sandbox?anchor=thirdParagraph.

When url query param is changed or screen is opened we check the value of anchor param, try to find a component with the same Id and focus it if possible.

Hope this helps.

Regards,
Gleb

1 Like