I am creating a JS survey and i want to open an <input type="file"/> but is not opening.
Some background info:
- I'm using only JS
- I'm using a MVC architecture
- I'm rendering HTML dinamically on index.html file
I'm posting most code than nessary because i'm trying to practice software architecture, and i believe there is something fundamentally wrong in the way i'm developing the code and that is why the dialog box is not working.
If you can point out some flaws in the way i organize the code it would be helpful as well.
The HTML file: index.html
All the dinamically HTML will be rendering on <div id='app'> the default class is just for styling the theme
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SIB Mobile</title>
<link rel="stylesheet" href="src/css/app.css">
<script type="module" defer src="src/js/app.js"></script>
</head>
<body>
<div id="app" class="default"></div>
</body>
<script src="src/pwa/idb.js"></script>
<script src="src/pwa/fetch.js"></script>
<script src="src/pwa/promise.js"></script>
</html>
The app.js (the main JS file)
Here is the main JS file, it has a switch case router on the _handleRoutes(routes) method (kkk) that initializes a controller based on the url.
import dbConnection from '../pwa/dbConnection.js';
import homeController from './controllers/homeController.js'
import settingsController from './controllers/settingsController.js'
import downloadController from './controllers/downloadController.js';
import surveyController from './controllers/surveyController.js';
class App {
init() {
this._initWindow();
this._initServiceWorker();
this._initIndexedDB();
}
_initWindow() {
['hashchange', 'load'].forEach(ev => window.addEventListener(ev, () => {
const route = window.location.hash.slice(1);
this._handleRoutes(route);
}));
window.addEventListener('click', e => {
e.preventDefault();
if (e.target.tagName.toLowerCase() === 'a') {
const url = e.target.href.split('/');
const route = url[url.length - 1];
window.history.pushState(null, '', `#${route}`);
this._handleRoutes(route);
}
});
}
_initServiceWorker() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js')
.then(() => {
console.log('[App] Service worker registered successfully!');
})
.catch(err => console.log('[App] Faild to register sw', err));
}
}
_initIndexedDB() {
if ('indexedDB' in window) {
dbConnection.init();
}
}
_handleRoutes(route) {
switch (route) {
case "survey": surveyController.init(); break;
case "home": homeController.init(); break;
case "settings": settingsController.init(); break;
case "download": downloadController.init(); break;
default: homeController.init();
}
}
}
new App().init();
The homeView.js
This is the View on MCV responsible for creating the necessary markup to be rendered on the HTML file.
I created a handler to catch the click event on the input file element.
It extends a View class that has a renderPage method and a _parentElement property
import View from './view.js';
class HomeView extends View {
_headerTitle = 'Header Title v1.0.0';
_generateMainMarkup() {
return `
<main class="main">
<div class="container">
<input type="file" class="input"/>
</div>
</main>
`;
}
addHandlerFileUpload(handler) {
this._parentElement.addEventListener('click', e => {
const input = e.target.closest('input');
if (!input) return;
//Open file dialog
})
}
}
/*
<div class="btn-group btn-group--column">
<a href="survey" class="btn btn--primary">novo inquerito</a>
<a href="view" class="btn btn--primary">Visualizar inqueritos</a>
<a href="stats" class="btn btn--primary">Visualizar estatisticas</a>
<a href="download" class="btn btn--primary">Carregar Dados</a>
<a href="settings" class="btn btn--primary">Definicoes</a>
</div> */
export default new HomeView();
The HomeController.js
This is the Controller, it has an init method and a controlFileUpload method to catch the input file click event.
import view from "../views/homeView.js";
import dbConnection from '../../pwa/dbConnection.js';
class HomeController {
_data;
_controlFileUpload(input) {
// Get uploaded file here
}
init() {
view.renderPage();
view.addHandlerFileUpload(this._controlFileUpload.bind(this));
}
}
export default new HomeController();