Why is class JS is executing twice? - javascript

In general, the problem is this. I create a class, write output to the console, and output the code twice. What to do?
import { CoreValid } from "./core.component"
export class Validator extends CoreValid {
constructor(elementId, btn, dataName) {
super(btn)
this.$dataName = dataName
this.$el = document.querySelector(elementId)
}
init() {
this.$btn.addEventListener('click', this.haha.bind(this))
}
haha(event) {
event.preventDefault()
console.log('one')
}
}
And its main component
export class CoreValid {
constructor(btn) {
this.$btn = document.querySelector(btn)
this.init()
this.idCreate()
}
init() {}
idCreate(){}
}
And this is screen
enter image description here
And this is HTML
<form action="">
<input type="text" class="main-input" placeholder="Title" data-nav="title" id="1" name="">
<div class="block-colors">
<input type="text" data-nav="color" placeholder="RGB" id="2">
</div>
<button class="submit">Submit</button>
</form>

Related

How do I retrieve a variable from .js file?

How do I access a variable defined in a js file from a vue file? Is there a way to pass this variable to the vue file? In the code below, I've got a template.js file and a contact.vue file. I am converting mjml to html in the template file and I need to access the output saved to the plainHmtl variable from the vue file.
template.js
const mjml2html = require('mjml')
const Vue = require('vue')
const app = new Vue({
data: {
name: ''
},
template: `
<mj-section>
<mj-column>
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello {{ name }}</mj-text>
</mj-column>
</mj-section>`
})
const renderer = require('vue-server-renderer').createRenderer({
template: `
<mjml>
<mj-body>
<!--vue-ssr-outlet-->
</mj-body>
</mjml>`
})
renderer.renderToString(app).then(html => {
const htmlWithoutDataServerRenderedAttribute = html.replace(`data-server-rendered="true"`, '')
const plainHtml = mjml2html(htmlWithoutDataServerRenderedAttribute)
console.log(plainHtml.html)
})
contact.vue
<template>
<div class="sign_up" id="signupform">
<main role="main">
<div class="SignUp_container">
<form class="form-signup" #submit.prevent="processForm">
<input type="text" name="name" placeholder="Enter First Name" required/>
<input type="text" name="lname" placeholder="Enter Last Name" required/>
<input type="email" name="mailaddr" placeholder="Your email address" required/>
<div class="sign_cancel_buttons">
<router-link to="/">
<button id="canlbtn" type="cancel" class="clbtn">
Cancel
</button>
</router-link>
<button id="signupbtn" type="submit" name="sendmsg-button" class="signbtn">
Sign Up
</button>
</div>
</form>
</div>
</main>
</div>
</template>
<script>
export default {
methods: {
// how do I access plainHtml here?
}
}
</script>
In template.js, define a variable where you will have the final result of converting your html, once defined just add this to the end of the file:
export { varHTML }
Now in contact.vue you have to import and use the export we made from template.js, consider that you must modify the import path according to the case that you are handling for your files:
import { varHTML } from './template.js'
<script>
export default {
data() {
return {
plainHtml: null
}
}
methods: {
// how do I access plainHtml here?
// any method that is going to be needed now will have plainHtml available
},
created () {
this.plainHtml = varHTML
}
}
</script>

How to use new-bind with addeventListeners in ES6 - Javascript?

I am trying to add addEventlistener to DOM element which has #addButton id.I am using new binding method in ES6 but this does not work. How to call add function?
class ToDoApp {
constructor (settings) {
if (!settings) {
throw 'Todo App requires settings object';
}
this.addButtonHandler = document.querySelector(settings.addButtonSelector);
this.addButtonHandler.addEventListener('click', this.add);
}
add = () => {
console.log('heello');
}
}
const myTodo = new ToDoApp({
inputSelector: '#input',
addButtonSelector: '#addButton',
deleteButtonSelector: '#delete',
listContainerSelector: '#list'
});
HTML
<div id="container">
<div id="imputArea">
<form action="index.html" method="POST">
<input type="text" id="input" />
<input type="button" id="addButton" value="Add" />
</form>
</div>
<div id="listArea">
<ul id="list">
<li>
<input type="checkbox" />
<p id="task">Task 1</p>
<input type="button" id="delete" value="X" />
</li>
</ul>
</div>
</div>
I guess you are getting this error due to the fact that element would not exist when you create an instance of newTodo. you might want to put null check for the button you are trying to add event listener to.
class ToDoApp {
constructor(settings) {
if (!settings) {
throw 'Todo App requires settings object';
}
this.addButtonHandler = document.querySelector(settings.addButtonSelector);
if (this.addButtonHandler) {
this.addButtonHandler.addEventListener('click', this.add);
} else {
throw "Element you want to add event listener to doesn't exist";
}
}
add = () => {
console.log('heello');
}
}
const myTodo = new ToDoApp({
inputSelector: '#input',
addButtonSelector: '#addButton',
deleteButtonSelector: '#delete',
listContainerSelector: '#list'
});

How can I display required html 5 in vue component?

My vue component like this :
<template>
<div>
...
<form class="form-horizontal" id="form-profile">
...
<input type="number" class="form-control" required>
...
<button type="submit" class="btn btn-primary" #click="submit">Submit</button>
...
</form>
...
</div>
</template>
<script>
export default {
...
methods: {
submit(e) {
e.preventDefault()
if (this.checkForm()) {
// do ajax here
}
},
checkForm() {
let field = true
$('#form-profile :required').each(function(i) {
if(this.checkValidity() == false)
field = false
})
return field
},
}
}
</script>
I using required html5 to validation
I using e.preventDefault() to prevent page redirects. Because I want to using ajax
My problem here is the required validation html5 not show if not filled. Maybe it because I using e.preventDefault()
How can I display the required html5?
In order to work as expected you have to set the v-on:submit method on the form tag, and have a button/input type "submit".
Also, notice the event modifier prevent on the #submit, it's a shorcut to not have to write e.preventDefault() on the method
new Vue({
el: '#app',
data() {
return {
myText: ''
}
},
methods: {
submitForm() {
alert('submited: ' + this.myText)
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="app">
<form #submit.prevent="submitForm">
<input type="text" v-model="myText" required />
<button type="submit">Submit</button>
</form>
</div>

onChange method not getting called from input

I am having a button from which I open the file explorer. I am doing it like this
{
this.props.fileUploadIsOpen
&& <div className='assign-dialog'>
<div className='assign-dialog-inner'>
<div className='dia-title'> File Upload</div>
<div className='dia-body'>
<div className='control-container'>
<div className='control-label'> Video File</div>
<div className='control'>
<input type="text" className="form-control" id="usr"/>
<button type="button" className="btn btn-primary" onClick={(e) => this.upload.click()}>Browse</button>
<input id="myInput" type="file" ref={(ref) => this.upload = ref} style={{visibility: 'hidden', width:0}} onChange={this.handleFileSelect}/>
</div>
</div>
But onChange method is not getting called. When I select a file, nothing happens. onChange method is supposed to called handleFileSelect function, which prints the file name in console. But nothing happens in console. Is onChange not getting triggered? How can I solve it?
I do not know why you are passing a function to the ref attr, but
I have recreated your case and it nails what you want
class Uploader extends React.Component {
constructor () {
super();
}
onClick (e) {
const {fileUpload} = this.refs;
fileUpload.click();
}
// prints the file name
handleFileSelect (e) {
const {fileUpload} = this.refs;
console.log(fileUpload.files[0].name)
}
render () {
return (
<div>
<div className='control-label'> Video File</div>
<div className='control'>
<input type="text" className="form-control" id="usr"/>
<button
type="button"
className="btn btn-primary"
onClick={this.onClick.bind(this)}>Browse</button>
<input id="myInput" type="file" ref="fileUpload" style={{visibility: 'hidden', width:0}} onChange={this.handleFileSelect.bind(this)}/>
</div>
</div>
);
}
}
Because you didn't call handleFileSelect function here and it call by your eventListener, you need to bind it, like this code:
this.handleFileSelect.bind(this)

React/ES6: Trouble Importing a Script

EDIT: Pinpointed the issue: This code is causing it not to work. If I change it from this:
{this.state.formVisible
? <Form onClick={this.hideForm}/>
: <AddBtn onClick={this.showForm}/>
}
to this:
<Form/>
it works? Why? I don't understand why I can't show and hide the form component and still have the script work???
I'm having trouble correctly using a script in my React app. It was working correctly when I rendered the form directly inside a component (App.js), but I moved the form over to it's own component and now render the component inside App.js, and now the imported scripts won't work.
Here's the breakdown of the two files (the script I need to run is custom.js). As you can see, importing the script into either file doesn't work, as the script is never used.
The first file that renders the "Form" component (App.js):
import React, {Component} from 'react';
import './App.css';
var script = require('./custom.js');
import AddBtn from './AddBtn.js';
import Form from './Form.js';
class App extends Component {
constructor(props, context) {
super(props, context);
this.state = {
formVisible: false
};
};
showForm = () => {
this.setState({formVisible: true});
}
hideForm = () => {
this.setState({formVisible: false});
}
render() {
return (
<div className="header">
<h1 id="p2">Contact Book</h1>
<form className="search">
<input type="text" name="search" placeholder="Search by last name"/>
<button type="button">Search</button>
</form>
{this.state.formVisible
? <Form onClick={this.hideForm}/>
: <AddBtn onClick={this.showForm}/>
}
</div>
);
}
}
export default App;
The second file that contains the form:
import React, {Component} from 'react';
var script = require('./custom.js');
class Form extends Component {
render() {
return (
<form id="addform">
<input type="text" name="fname" placeholder="First name" required/>
<input type="text" name="lname" placeholder="Last name" required/>
<input type="email" name="email" placeholder="email" required/>
<input type="input" name="address" placeholder="address" required/>
<input type="tel" name="phone" placeholder="phone number" required/>
<input type="submit" id="submitbtn" value="Submit"/>
<button type="button" id="closebtn" onClick={this.props.onClick}>Close</button>
</form>
);
}
}
export default Form;
AAAAND the script itself (which doesn't really matter. I already know it works correctly.)
import $ from 'jquery';
//will hold an array of people objects
var list = [];
//constructor that builds new people to add to address book
function Person(first, last, email, address, phone) { //new person constructor
this.firstName = first;
this.lastName = last;
this.email = email;
this.address = address;
this.phone = phone;
};
$(document).ready(function () {
// When the submit button is clicked, create a new person and add the values of
// the form fields to the properties of the object
$("#addform")
.submit(function (e) {
e.preventDefault();
var person = new Person($("input[name = 'fname']").val(), $("input[name = 'lname']").val(), $("input[name = 'email']").val(), $("input[name = 'address']").val(), $("input[name = 'phone']").val());
list.push(person);
console.log(list);
});
});
Instead of relying on DOM nodes which is how jQuery operates, stick within the realm of React.
class Form extends Component {
handleSubmit = e => {
e.preventDefault();
let data = new FormData(e.target)
for (let [key, val] of data.entries()) {
// do something with your data
console.log(key, val);
}
}
render() {
return (
<form id="addform" onSubmit={this.handleSubmit}>
<input type="text" name="fname" placeholder="First name" required/>
<input type="text" name="lname" placeholder="Last name" required/>
<input type="email" name="email" placeholder="email" required/>
<input type="input" name="address" placeholder="address" required/>
<input type="tel" name="phone" placeholder="phone number" required/>
<input type="submit" id="submitbtn" value="Submit"/>
<button type="button" id="closebtn" onClick={this.props.onClick}>Close</button>
</form>
);
}
}
This way you don't need your external script at all, or jQuery for that matter, and you can keep your conditional ternary in your parent component the way it is.

Categories