document.querySelector causing errors on other methods when called - html

My apologies for the stupid question, but I am trying to change the name of a button upon uploading a file. My code to change it is this, via TypeScript:
const i = (document.querySelector('label') as any).innerText = filename;
The code above, inside the fileName method, changes the "Upload Project File" text into the name of whatever file that is uploaded.
<div class="row">
<div class="clg6 cmd8 csm10 cxs12" v-if="this.projectFile">
<button
class="button primary outline medium upload">
<label>
<input
type="file"
name="projectFile"
id="fileName"
accept=".xls, .xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
v-on:change="validateFileType(); hashContentMD5(); fileName; getPresignedURL()"/>
<i class="fas fa-cloud-upload"></i>
Upload Project File
</label>
</button>
</div>
</div>
And it works. However, upon change, it brings up errors in my other methods when they're called, such as this:
const file = (document.getElementById('fileName')as any).files[0]
The error that shows up is
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'files')
Removing the document.querySelector removes the error. This is the first time that I've encountered this. How can I fix it?

Problems:
You put your input inside the label tag. I learned this is okay.
Why using a button outside the whole label and input tags? I don't understand what your intention was with that.
You replace the inside of the label tag by a text node (containing the file name). Through your replacement you delete your input field out of the DOM. See querySelector line in your code.
After having replaced the input field, there is no fileName on the page anymore, so it getElementById results in null.
Solution:
(optionally) I'd delete the button tag and only keep the inside of it.
Don't operate on that label and don't try to overwrite the value of a file input field
By not removing the input field anymore, you can access it and read out the file name
See my example here: https://stackblitz.com/edit/js-fdxxnf

You can try with ref:
new Vue({
el: '#demo',
data() {
return {
projectFile: true
}
},
methods: {
changeLbl() {
this.$refs.lab.innerText = 'filename'
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div class="row">
<div class="clg6 cmd8 csm10 cxs12" v-if="projectFile">
<button
class="button primary outline medium upload">
<label ref="lab">
<input
type="file"
name="projectFile"
id="fileName"
accept=".xls, .xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
v-on:change="changeLbl"/>
<i class="fas fa-cloud-upload"></i>
Upload Project File
</label>
</button>
</div>
</div>
</div>

Related

How to instantiate a variable in Nuxt

I've tried a couple of different ways to instantiate a variable in Nuxt but neither way seems to work. I have read around the subject and suspect that perhaps what I'm trying to do is not compatible with Webpack but I'm not sure how.
Here is a jsFiddle of the code: jsfiddle.net/tutmoses/z2365g49/4
First in the script section I export dataSize:
<script>
export default {
data(){
return {
page_name: "Run Model",
dataSize: 1296
}
}
</script>
Then in the HTML above I'm trying to import it but nothing renders:
<div class="setting">
<span class="setting-label">Training Size:</span>
<input id="trainingSize" :value="dataSize"></input>
</div>
I've also tried this:
<div class="setting">
<span class="setting-label">Training Size:</span>
<input id="trainingSize" :value= {{ dataSize }}></input>
</div>
...but the value instantiates as
{{
I've tried both of the above options without binding the value but that didn't work either.
Another way I've tried is this in a separate file:
export const nnSettings = {
dataSize: 1296
}
And then importing it with this:
import nnSettings from '~/components/testindex.js'
Again, zip.
The reason why I'm importing the value is because other values will be calculated from it. What would be the standard, best way to do it?
Nuxt (Vue) uses v-model to bind to form input. Have a look here for more info on form bindings
<div class="setting">
<span class="setting-label">Training Size:</span>
<input id="trainingSize" v-model="dataSize"></input>
</div>

Electron Get file path from form and display as text

I am creating a simple program in Electron. The program has the option of running several separate functions based on what the user needs. All functions require a file to be inputted and a save location for the resulting output file. This is done using a form. I would like to have it that once the user inputs the locations it is displayed in a div beside the input buttons. Is there a way to do this within electron?
code:
<!-- File Input Section -->
<div class = "individual-input-container-2">
<div class="input-container" >
<div class = "inner-input-container">
<input type="file" id="file-input" class = "input-top" >
<p class = "input-desc-file">File</p>
</div>
<div>
</div>
</div>
<div class="input-container">
<div class = "inner-input-container">
<input type="file" webkitdirectory id="save-input"class = "input-bottom">
<p class = "input-desc-save">Save Location</p>
</div>
</div>
</div>
Here is photo of what I am building
I did something similar a while back and mine looks like this:
HTML:
<button id="choosePath">Choose Folder</button>
JS:
const { dialog } = require('electron').remote;
document.querySelector('#choosePath').addEventListener('click', (e) => {
dialog.showOpenDialog({
title:"Select Directory",
properties: ["openDirectory"]
}, (folderPaths) => {
// folderPaths is an array that contains all the selected paths
if(folderPaths === undefined){
return;
} else {
// Do something with the folderPaths variable
}
});
});
It's basically just an ordinary button opening a Dialog Window where you can select a path.
If you did select one the full Path is passed to a callback function where you can use it to do whatever you have to do with it.
You can try Electron's dialog.showSaveDialog ()/dialog.showSaveDialogSync () functions. They return a Promise<string> or a string representing the file/folder which was selected by the user, respectively. Then you can easily display in your <div>.

How to reset check status in html

I have popup in HTML
<div id="term_flags" class="term_flags">
<div class="modal-users-content flagsContent">
<div class="modal-users-header">
<span class="close" ng-click="closeFlagsPopup()">×</span>
<a> Check terminal flags </a>
</div>
<div class="modal-flags-body">
<div class="checkBoxes">
<div class="checkerDiv">
<input type="checkbox" ng-model='reservedFlag' ng-click='changeReservedStatus(reservedFlag)' value="flag" ng-checked="reservedFlag"> Reserved
</div>
<div class="checkerDiv">
<input type="checkbox" ng-model='seasonFlag' ng-click='changeSeasonStatus(seasonFlag)' value="flag" ng-checked="seasonFlag"> Season
</div>
<div class="checkerDiv">
<input type="checkbox" ng-model='networkFlag' ng-click='changeNetworkStatus(networkFlag)' value="flag" ng-checked="networkFlag"> Network
</div>
</div>
<div class="saveFlags">
<button class="button button6" name="changeFlags" value="Change Flags" type="submit" ng-click="saveFlags(item.terminalId)"> Save <p> </button>
</div>
</div>
<div class="modal-footer"></div>
</div>
</div>
this div's display is none in the beginning. but some ng-click is called from outside of this div and display is changed from none to block and initializes checkbox statuses in this angular function
$scope.changeFlagStatus = function(item)
{
$scope.reservedFlag=(item.reservedFlag=='T')?true:false;
$scope.networkFlag=(item.networkFlag=='T')?true:false;
$scope.seasonFlag=(item.seasonFlag=='T')?true:false;
document.getElementById('term_flags').style.display = "block";
}
everything is okay , but when i click on reservedFlag changeReservedStatus(reservedFlag) method was called and change reservedFlag's checked status
$scope.changeReservedStatus = function(item) {
$scope.reservedForSave=item;
}
I saved this status in other variable and close my popup windows document.getElementById('term_flags').style.display=none
when i open this popup window again my function changeFlagStatus(item) is called again and initializes my variables for checkbox correctly but my checkbox are incorrect checked .
In example when i opened my popup window first time my variables after initialize were
$scope.reservedFlag=true;
$scope.networkFlag=false;
$scope.seasonFlag=true;
and my checkbox statuses were
reservedFlag = checked
networkFlag = unchecked
seasonFlag = checked
then i clicked on reservedFlag and changed his status from checked to unchecked and close my popup windows.
then i opened it second time and changeFlagStatus(item) method is called again to initialize my variables again for checkbox statuses
and i want to get
reservedFlag = checked
networkFlag = unchecked
seasonFlag = checked
again, but result is
reservedFlag = unchecked
networkFlag = unchecked
seasonFlag = checked
How can i get it ?
Angularjs won't work pretty good with $scope's properties for primitive variables when used again and again.
I would recommend you to declare an object to scope and set these flags as properties to this object.
$scope.flags = {};
$scope.changeFlagStatus = function(item)
{
$scope.flags.reservedFlag=(item.reservedFlag=='T')?true:false;
$scope.flags.networkFlag=(item.networkFlag=='T')?true:false;
$scope.flags.seasonFlag=(item.seasonFlag=='T')?true:false;
document.getElementById('term_flags').style.display = "block";
}
and the html part as
<input type="checkbox" ng-model='flags.reservedFlag' ng-change='changeReservedStatus()' value="flag" ng-checked="flags.reservedFlag"> Reserved
Instead of ng-click, I would recommend to use ng-change because that is the event to be used with checkbox. If you use ng-change, the injection of the model as a parameter can be avoided which helps in utilizing angularjs's feature of 2-way binding.
You can add ng-true-value and ng-false-value to the checkbox with true and false to make it more easier to handle instead of ng-value.
I would write the html part like this.
<input type="checkbox" ng-model='flags.reservedFlag' ng-change='changeReservedStatus()' ng-true-value="true" ng-false-value="false"> Reserved
Hope this will fix the issue.

Stop Picker from closing after coming to end of HTML

I press a button/image to run script that opens the picker. I can select an existing folder and I have added a field to create a new folder (within the selected existing folder).
All of this works as I want, but I added some error handling incase the button to create a new folder was pressed without a folder name being given. I put the message in an alert (may need to amend that as it gives the option to 'prevent this page from displaying additional dialogues') but once the alert has gone, the html disappears.
What do I do to retain the HTML that was in the IFRAME before the button was pressed?
This is my HTML code and the function behind the button.
</head>
<body>
<div>
<p> Please select the property you wish the ticket folder to be created in. </p>
<button onclick='getOAuthToken()'>Select a Folder</button>
<br>
<p> (If it does not exist, select the folder you wish to create a new location in.) </p>
<p id='result'></p>
</div>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
<br><br><br>
<div id="frmCreate" style="display:none">
<form>
<label class="hiddenfrm"> Folder Name: </label><input type="text" id="newFdrNm" class="hiddenfrm">
<button onclick='makeFolder()' class="hiddenfrm">Create New Folder</button>
<p id='newresult' class="hiddenfrm"></p>
</form>
</div>
</body>
</html>
//function to create a folder in the selected folder
function makeFolder() {
var ParentFolder = document.getElementById('PFldrID').innerHTML
var NewFolderName = document.getElementById('newFdrNm').value
if (NewFolderName == "") {
alert("Folder Name Required!")
}
else {
google.script.run.CreatePropertyFolder(NewFolderName, ParentFolder);
google.script.host.close();
}
}
EDIT:
After removing the form tags, the dialogue box works as required.
For the alert, I decided to have the error message display under the text box.
Amended parts of the code:
*HTML*
<button onclick='makeFolder()' class="hiddenfrm">Create New Folder</button>
<br><span id="newFdrNmError"></span>
*script*
if (NewFolderName == "") {
document.getElementById('newFdrNmError').innerHTML = "Error: You must 'name' the new folder!";
return false;
}
The HTML in the window is disappearing because the "Create New Folder" button is inside of the <form> tags. There is nothing that I know of that can stop that from happening, except moving the button outside of the <form> tags.
Move button:
<form>
<label class="hiddenfrm"> Folder Name: </label><input type="text" id="newFdrNm" class="hiddenfrm">
<p id='newresult' class="hiddenfrm"></p>
</form>
<button onclick='makeFolder()' class="hiddenfrm">Create New Folder</button>

Id duplicates when using templates in parse / backbone / js / html

I get duplicate ids when I set the views like so in my render function
var template = _.template($("#user-login-template").html(), {});
this.$el.html(template);
The html looks like this after running the render function, before runing the render function. Beforehand, the <div class ="app"> is empty (as it should be). It copy pasted the code from template and therefore the ids into the div.
<div class="app">
<input type="text" id="signup-username" placeholder="Username"/>
<input type="password" id="signup-password" placeholder="Create a Password"/>
<button id="signUpBtn">Sign Up</button>
<button id="logInBtn">Login</button>
</div>
<!-- Templates -->
<!-- Login Template -->
<script type="text/template" id="user-login-template">
<input type="text" id="signup-username" placeholder="Username"/>
<input type="password" id="signup-password" placeholder="Create a Password"/>
<button id="signUpBtn">Sign Up</button>
<button id="logInBtn">Login</button>
</script>
For reference, this is what my whole view looks like
var LogInView = Parse.View.extend({
el: '.app',
events: {
"click .signUpBtn": "signUp",
"click .logInBtn": "logIn"
},
initialize: function (){
this.render()
},
logIn: function () {
//To Do
},
render: function () {
var template = _.template($("#user-login-template").html(), {});
this.$el.html(template);
}
});
If Webstorm is complaining about the ids inside the <script> then it is wrong and you have three options:
Get a new IDE that has a better understanding of HTML.
Figure out how to reconfigure Webstorm to know what HTML really is. There must be a way to beat some sense into Webstorm, this sort of thing is very common these days.
Ignore the warnings (yuck).
Things inside <script> are not HTML and are not part of the DOM. Ask the browser what $('input[type=text]').length is after your template is rendered and you'll get 1 since the
<input type="text" id="signup-username" placeholder="Username"/>
inside the <script> isn't HTML, it is just text. You can even check the HTML specification of <script>:
Permitted contents
Non-replaceable character data
Non-replaceable character data is not HTML, it is just text.