英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论