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

javalinVue: not able to get LoadableData to work #2075

Open
cyrilou242 opened this issue Jan 6, 2024 · 2 comments
Open

javalinVue: not able to get LoadableData to work #2075

cyrilou242 opened this issue Jan 6, 2024 · 2 comments

Comments

@cyrilou242
Copy link

Hey, I'm trying to use javalinvue.
I went through the tutorial without issues.

I'm now trying to use LoadableData.
I tried copy pasting the snippet here: https://javalin.io/plugins/javalinvue#loadabledata

<template id="books-component">
    <div>
        <div v-if="books.loading">Loading books ...</div>
        <div v-if="books.loadError">Failed to load books! ({{books.loadError.text}})</div>
        <div v-if="books.loaded" v-for="book in books.data">{{book}}</div>
    </div>
</template>
<script>
    app.component("books-component", {
        template: "#books-component",
        data: () => ({
            books: new LoadableData("/api/books"),
        }),
    });
</script>

But somehow the rendered html is stuck at Loading books ....
It seems the Vue reactivity does not work.

Opening this as a question as I suspect I'm missing something dumb.

My pom dependencies is the following:

    <dependency>
      <groupId>io.javalin</groupId>
      <artifactId>javalin-bundle</artifactId>
    </dependency>
    <dependency>
      <groupId>org.webjars.npm</groupId>
      <artifactId>vue</artifactId>
    </dependency>

And here is the generated html if this helps:

<html>
<head>
  <meta charset="utf8">
  <script src="/webjars/vue/3.3.9/dist/vue.global.prod.js"></script>
  <script>
    const app = Vue.createApp({});
  </script>
  

<script >
    class LoadableData {
        constructor(url, cache = true, errorCallback = null) {
            this._url = url;
            this._errorCallback = errorCallback;
            this.refresh(cache);
            this.addRefreshListener();
        }
        refresh(cache = true) {
            this.data = null;
            this.loading = true;
            this.loaded = false;
            this.loadError = null;
            let cacheKey = "LoadableData:" + this._url;
            if (cache) {
                this.data = JSON.parse(localStorage.getItem(cacheKey)) || null;
                this.loaded = this.data !== null;
                this.loading = this.loaded === false;
            }
            fetch(this._url).then(res => {
                if (res.ok) return res.json();
                throw JSON.stringify({code: res.status, text: res.statusText});
            }).then(data => {
                this.data = data;
                this.loaded = true;
                if (cache) {
                    localStorage.setItem(cacheKey, JSON.stringify(data));
                }
            }).catch(error => {
                this.loadError = JSON.parse(error);
                if (this._errorCallback !== null) { // should probably handle in UI
                    this._errorCallback(error);
                }
            }).finally(() => this.loading = false);
        }
        refreshAll() {
            LoadableData.refreshAll(this._url);
        }
        static refreshAll(url) {
            window.dispatchEvent(new CustomEvent("javalinvue-loadable-data-update", {detail: url}));
        }
        addRefreshListener() {
            window.addEventListener("javalinvue-loadable-data-update", e => {
                if (this._url === e.detail) {
                    this.refresh(false);
                }
            }, false);
        }
    }
</script><!-- books-component -->
<template id="books-component">
  <div>
    <div v-if="books.loading">Loading books ...</div>
    <div v-if="books.loadError">Failed to load books! ({{books.loadError.text}})</div>
    <div v-if="books.loaded" v-for="book in books.data">{{book}}</div>
  </div>
</template>
<script>
app.component("books-component", {
  template: "#books-component",
  data: () => ({
    books: new LoadableData("/api/books"),
  }),
});
</script>

<script >
    app.config.globalProperties.$javalin = JSON.parse(decodeURIComponent('%7B%22pathParams%22:%7B%7D,%22state%22:%7B%22currentUser%22:null%7D%7D'))
</script>
</head>
<body>
<main id="main-vue" v-cloak>
  <books-component></books-component>
</main>
<script>
  app.mount("#main-vue");
</script>
</body>
</html>
@tipsy
Copy link
Member

tipsy commented Jan 7, 2024

It seems the Vue reactivity does not work.

This is a known issue, there is a PR attempting to fix this: #2070

Other PRs (or help on the current one) would be appreciated :)

@cyrilou242
Copy link
Author

Oh ok thanks!
I'll follow the PR.
Will look at the other PRs once I know more about javalin. I'm starting a side project with it.
Thanks for the swift response and the great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants