Vaadin 14.4.0可以操作浏览器的后退/前进历史按钮(可能使用onHashChange)。

huangapple go评论65阅读模式
英文:

Vaadin 14.4.0 manipulate the back/forward history buttons (onHashChange perhaps)

问题

我有一个单页面、单类的 Vaadin 项目。在这个项目中,我可能会更改布局,使其看起来像是进入了一个新页面。但由于没有打开新的链接/页面,我无法弄清楚如何允许用户“返回”到先前的元素。

一度我以为我可以改变URL,然后捕捉用户是否使用前进或后退按钮。我找到了 hashChange 事件,但我无法理解它或使其起作用。Vaadin 有一个 HistoryChangeEventHandler,但它不会监听 hashChanges,因此我的解决方案行不通。

对于解决这个问题,我一直没有头绪。我找到了这个帖子,它是2019年的,看起来是解决我的问题的方法,但是我无法让代码工作。我猜想我可能在将错误的元素传递给 JavaScript 执行。

因此,我有一个继承自 div 的简单的 mainview。在这个 div 中,我有以下代码:

History history = UI.getCurrent().getPage().getHistory();
TextField textField = new TextField();
add(textField);

Button button = new Button();
button.setText("New link");
button.addClickListener(e -> history.pushState(null, "#" + textField.getValue()));
add(button);

Button button1 = new Button();
button1.setText("Go back");
button1.addClickListener(e -> history.back());
add(button1);

getElement().executeJs(
    "const serverCallback = element.$server.onHashChange; this.window.addEventListener('hashchange', function () {serverCallback(location.hash);}, false);"
);

@ClientCallable
public void onHashChange(String hash) {
    System.out.print("test " + hash);
}

我预期 onHashChange 方法会被调用。但我得到一个 JavaScript 错误,说:(ReferenceError):element 未定义。

可行的解决方案:

getElement().executeJs("const serverCallback = $0.$server.onHashChange;" +
    "window.addEventListener('hashchange', function () {serverCallback(location.hash);}, false);",  getElement());

我的 getElement() 是扩展的 div,我猜。这是我的 onHashChange 方法。

@ClientCallable
public void onHashChange(String location) {
    System.out.println("Current location is: " + location);
}

此外,如果你想从 Vaadin 调用一个 Java 方法。你可以这样做:

getElement().executeJs("$0.$server.onHashChange(\"It works\");",  getElement());

祝你好运!并且非常感谢 Erik 抽出时间来帮助解决问题。

英文:

I have a single page, single class Vaadin project. In this project, I might change the layout to make it seem as if a new page has been entered. But since no new link/page is approached, I cannot figure out how to allow users to "return" to the previous element.

For a bit, I thought I could change the url, and then catch whether people used the forward or backward buttons. I have found hashChange events, but I cannot make sense of it or make it work. Vaadin has a HistoryChangeEventHandler, but it does not listen for hashChanges, and as such my solution would not work.

I am coming up short with regards to solving this. I found this thread from 2019, which seems to be a solution to my issue, but I cannot make the code work. I suppose I am trying to pass a wrong element to the javaScript execution.

So, I have a simple mainview that extends a div. In this div, I have the following code:

History history = UI.getCurrent().getPage().getHistory();
    TextField textField = new TextField();
    add(textField);

    Button button = new Button();
    button.setText("New link");
    button.addClickListener(e-> history.pushState(null, "#"+textField.getValue()));
    add(button);

    Button button1 = new Button();
    button1.setText("Go back");
    button1.addClickListener(e-> history.back());
    add(button1);

    getElement().executeJs(
            "const serverCallback = element.$server.onHashChange; this.window.addEventListener('hashchange', function () {serverCallback(location.hash);}, false);"
    );

@ClientCallable
public void onHashChange(String hash) {
    System.out.print("test "+hash);
}

I expected that the onHashChange method would be called. But I am getting a javascript error saying: (ReferenceError) : element is not defined.

Working solution:

getElement().executeJs("const serverCallback = $0.$server.onHashChange;" +
            "window.addEventListener('hashchange', function () {serverCallback(location.hash);}, false);",  getElement());

My getElement() is the extended div, I guess. And here is my onHashChange method.

@ClientCallable
public void onHashChange(String location) {
    System.out.println("Current location is: " + location);
}

Also, if you ever wanted to just call a java method from vaadin. You can do the following:

getElement().executeJs("$0.$server.onHashChange(\"It works\");",  getElement());

Good luck! And thank you Erik for taking the time to help out.

答案1

得分: 2

查看executeJs的JavaDoc,它说:

 * 异步地在浏览器中以此元素的上下文运行给定的JavaScript表达式。
 * ...
 * 此元素将作为表达式中的<code>this</code>可用。

因此,尝试将element.$server替换为this.$server

英文:

Looking at the JavaDoc for executeJs, it says:

 * Asynchronously runs the given JavaScript expression in the browser in the
 * context of this element.
 * ...
 * This element will be available to the expression as <code>this</code>.

So try replacing element.$server with this.$server.

huangapple
  • 本文由 发表于 2020年10月19日 19:13:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/64426155.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定