vanjs-org / van

🍦 VanJS: World's smallest reactive UI framework. Incredibly Powerful, Insanely Small - Everyone can build a useful UI app in an hour.
https://vanjs.org
MIT License
3.77k stars 87 forks source link

Element not rendering properly #342

Closed emanjavacas closed 2 months ago

emanjavacas commented 2 months ago

Hi! First of all thanks for this amazing package, I just started playing around and after a few hours of trying to figure out my issue I am writing to see if you can point me in the right direction.

I am writing an app that lets users upload files and processes them updating the users about the status.

Info about the files is stored in a list (I created the following structure):

    class FileList {
        constructor (files) { this.files = files }
        add (filename, sessionId, status) {
            this.files.push({ filename: filename, sessionId: sessionId, status: van.state(status)});
            return new FileList(this.files);
        }
        updateStatus(sessionId, status) {
            const file = this.files.find(f => f.sessionId === sessionId);
            if (file) {
                file.status = van.state(status);
            }
            return new FileList(this.files);
        }

    }

    const filelist = van.state(new FileList([]));

When adding an item to this list, I am expecting an update on the front end, the only I get to see is [object HTMLLIElement].

I am adding the relevant code down here.

Updating state:

    function addFileToList(filename, sessionId, status) {
        console.log('addFileToList', filename, sessionId, status);
        filelist.val = filelist.val.add(filename, sessionId, status);
    }

    function updateFileStatus(sessionId, status) {
        filelist.val = filelist.val.updateStatus(sessionId, status);
        console.log('updateFileStatus', sessionId, status);
    }

Creating elements for rendering:

    function Card() {
      function createListItem(file) {
          console.log('createListItem', file);
          const statusClasses = {
              UPLOADING: 'bg-warning text-dark',
              PROCESSING: 'bg-info',
              READY: 'bg-success'};
          const statusClass = statusClasses[file.status.val] || 'bg-seconday';
          const listItem = li({ class: 'list-group-item' },
              span(file.filename), 
              file.status.val == READY ? 
                  button({ id: `btn-${file.sessionId}`, 
                      class: "btn btn-sm btn-primary float-end",
                      onclick: () => downloadFile(file.sessionId) }, "Download") :
                  button({ id: `btn-${file.sessionId}`, class: "btn btn-sm btn-primary float-end disabled" }, "Download"),
              div(span({ id: `status-${file.sessionId}`, class: statusClass }, file.status.val)))
          return listItem
      }

      return div({ class: "card" }, 
          div({ class: "card-header" }, "AI Detection Service"),
          div({ class: "card-body" },
              h5({ class: "card-title" }, "File Upload"),
              p({ class: "card-text" }, "Upload a text file for further analysis."),
              form({ class: "input-group", id:"uploadForm", onsubmit: onSubmit },
                  input({ type: "file", class: "form-control", id: "fileInput", multiple: true }),
                  button({ class: "btn btn-outline-secondary", type: "submit" }, "Upload"))),
          div({class:"row"},
              ul({ class: "list-group list-group-flush", id: "fileList" },
              () => filelist.val.files.map(createListItem))))

This is how I add it to the document:

$(document).ready(function() {
    van.add($("#entryPoint"), Card())
});

I've been trying several ways but somehow nothing turns up as expected. Any help appreciated!

emanjavacas commented 2 months ago
Screenshot 2024-06-17 at 19 39 40
sirenkovladd commented 2 months ago

Can you try to replace

() => filelist.val.files.map(createListItem)

to

() => div(filelist.val.files.map(createListItem))
emanjavacas commented 2 months ago

hey thanks for chiming in!

I did try but it behaves the same somehow.

I've put all the code on this repo: https://github.com/emanjavacas/LLM-detect/blob/main/static/main.js

Tao-VanJS commented 2 months ago

This line https://github.com/emanjavacas/LLM-detect/blob/5d23dc0828254970ce1858e057a3ea6e97281ed2/static/main.js#L133, needs to be changed to

() => div(filelist.val.files.map(createListItem))

as @sirenkovladd suggested, basically, for state-derived DOM nodes, we don't support binding functions that return an array. You need to wrap the array of DOM nodes with a pass-through container element like <div>.

emanjavacas commented 2 months ago

Oh thanks for the quick response.

Yes indeed I managed to solve this! Thanks for your help and feel free to close the issue ,

Enrique Manjavacas

On Mon, 17 Jun 2024 at 20:11, Tao Xin @.***> wrote:

This line https://github.com/emanjavacas/LLM-detect/blob/5d23dc0828254970ce1858e057a3ea6e97281ed2/static/main.js#L133, needs to be changed to

() => div(filelist.val.files.map(createListItem))

as @sirenkovladd https://github.com/sirenkovladd suggested, basically, for state-derived DOM nodes, we don't support binding functions that return an array. You need to wrap the array of DOM nodes with a pass-through container element like

.

— Reply to this email directly, view it on GitHub https://github.com/vanjs-org/van/issues/342#issuecomment-2174025600, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPIPI7JU4OOIU5QYNSTIXLZH4RFHAVCNFSM6AAAAABJOOJBOGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNZUGAZDKNRQGA . You are receiving this because you authored the thread.Message ID: @.***>