I want to get ListFile. I wrote this code.
include karax / prelude
proc createDom(): VNode =
result = buildHtml(tdiv):
h1:
text "hello world"
input(`type`="file"):
text "click here"
proc onchange(ev: Event, n: VNode) =
echo ev[]
echo ev.target[]
echo n[]
setRenderer createDom
But I couldn't find files or target.files.
I could get ListFile on JavaScript.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
window.onload = function() {
const elem = document.getElementById('fileButton')
elem.addEventListener('change', click)
}
function click(ev) {
console.log(ev.target.files) // I want to get this.
}
</script>
</head>
<body>
<input id="fileButton" type="file" value="click" />
</body>
</html>
How can I get files in <input type="file">?
From a quick look at the karax source I can't see a way to get this.
Here's a quick workaround:
include karax / prelude
type
File = object
lastModified: cint
name: cstring
size: cint
`type`: cstring
proc createDom(): VNode =
result = buildHtml(tdiv):
h1:
text "hello world"
input(`type`="file"):
text "click here"
proc onchange(ev: Event, n: VNode) =
var files: seq[File]
asm """`files` = `ev`.target.files"""
echo "files: ", files
setRenderer createDom
This took a bit of digging, but it looks like you can cast nodes to different types (not sure if this is the best way):
include karax / prelude
import karax / kdom
proc createDom(): VNode =
result = buildHtml(tdiv):
h1:
text "hello world"
input(`type`="file"):
text "click here"
proc onchange(ev: Event, n: VNode) =
let element = cast[InputElement](ev.target)
let file = cast[kdom.File](element.files[0])
echo file.size
echo file.`type`
echo file.name
setRenderer createDom
I found the definitions of the DOM objects here: https://github.com/nim-lang/Nim/blob/version-1-0/lib/js/dom.nim#L242
Trying to acutally read the file using the FileReader API. I'm using Karax but would appreciate any examples in karax or just using std/dom.
I would expect that the following would work, but console.log shows null.
input(`type` = "file", id = "file-input"):
proc onchange(ev: Event; n: VNode) =
var element = InputElement(ev.target)
var reader = newFileReader()
reader.readAsText(element.files[0])
console.log(resultAsString(reader))
Unfortunately, I think the API was not understood when the code was written for FileReader. FileReader uses an event based API, so immediately running resultAsString will return too quickly as the file has not been read yet. It should be rewritten to something like:
nclude karax / prelude
import karax / kdom
proc resultAsString*(f: FileReader, callback: proc(res: cstring)) =
{.emit: """
`f`.onload = function () {
`callback`(`f`.result);
};
""".}
proc createDom(): VNode =
result = buildHtml(tdiv):
h1:
text "hello world"
input(`type`="file"):
text "click here"
proc onchange(ev: Event, n: VNode) =
let element = InputElement(ev.target)
let file = kdom.File(element.files[0])
echo file.size
echo file.`type`
echo file.name
var reader = newFileReader()
reader.readAsText(file)
resultAsString(reader, proc(res: cstring) = echo res)
setRenderer createDom