Vue.js with $this.refs? - javascript

<template>
<div>
<form>
<p ref="uploadCvText" #click="openUploadFileDialogueCV(this.$refs.input_file_cv)">+ Upload Your CV (*)</p>
<input ref="input_file_cv" type="file" value="" name="input_file_cv" #change="handleCvUpload()">
</form>
</div>
</template>
<script>
methods: {
openUploadFileDialogueCV(e) {
e.click();
}
}
</script>
the problem is that (ref) is not allowed to be used in template ! so how can i
refer to html element and let openUploadFileDialogueCV() function
works correctly ?

Just don't use this in template, use #click="openUploadFileDialogueCV($refs.input_file_cv) instead

Related

Display selected document from input type: file

I have this code
Html
<input type="file" accept=".docx" type="file" id="fileUpload" onchange="setFile()" />
Javascript
const setFile = () => { console.log(document.getElementById('fileUpload').files[0])}
And I'm trying to get the selected file to display in the console but to no avail. Pls how can I fix this?
Here is the sandbox link https://codesandbox.io/embed/fancy-river-9dn69?codemirror=1
Just reference the name property and you'll have what you're looking for.
const setFile = () => {
console.log(document.getElementById('fileUpload').files[0].name)
}
<input type="file" accept=".docx" type="file" id="fileUpload" onchange="setFile()" />
Other properties such as lastModified, lastModifiedDate, type and others are also available on it so just refer the onces you'll like to display.
"setFile()" treated as string not function call ,So to call SetFile() , You need to Call it , So use onChange={setFile()} , if you are working in react
const setFile = () => {
console.log(document.getElementById('fileUpload').files[0].name)
}
<input type="file" accept=".docx" type="file" id="fileUpload" onchange={setFile()} />
Your code is indeed extracting the info of the object file. Here you can see been rendered inside <body>
const setFile = () => {
const fileObject = document.getElementById('fileUpload').files[0];
document.getElementById('title').style.display = 'block';
document.getElementById('one').append('Name: ' + fileObject.name)
document.getElementById('two').append('Last Modified: ' + fileObject.lastModified)
document.getElementById('three').append('Last Modified Date: ' + fileObject.lastModifiedDate)
document.getElementById('four').append('Size: ' + fileObject.size)
document.getElementById('five').append('Type: ' + fileObject.type)
}
div{margin:10px 0}
<input type="file" accept=".docx" type="file" id="fileUpload" onchange="setFile()" />
<h1 id="title" style="display:none">File Info</h1>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>
<div id="five"></div>
Using a Label tag instead of button tag to trigger the file input helped resolve the issue. Although i can't understand why.

Problem incorporating data got from API vue.js

After get API call with a string input attached, I get the result alright. The problem I have is incorporating it to my frontend. I have tried a lot of solutions that I found online but nothing working and cannot understand. So far I have done this:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type = text/javascript src = https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.0.3/vue-resource.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<form action="http://127.0.0.1:1880/" target="_self">
<label for="request"><strong>Please insert the input here:</strong></label><br>
<input type="text" id="request" name="input"><br>
<button v-on:click="getOverview($event)">Submit</button>
</form>
<h1 id="results" v-for="overview in overview">
{{overview}}
</h1>
<script type = text/javascript >
new Vue({
el: "#results",
data() {
return {
overview: []
}
},
methods: {
async getOverview(event) {
try {
const {data:{json:{sub_regions}}} = await axios.get('http://127.0.0.1:1880/');
console.log('results data', sub_regions);
this.overview = sub_regions;
}
catch (error) {
console.log(error);
return [];
}
}
},
created(){
this.getOverview()
}
})
</script>
</body>
</html>
I am a bit lost with javascript as I am new to it, all kinds of help are welcome,
Thank you in advance! :)
EDIT: the file I get from the API is JSON
Looks as though you are trying to call a method outsides of the vue app itself.
You have the el: "results" but you are trying to invoke a vue method within your button outside of its context.
Try something like this:
<div id="results">
<form action="http://127.0.0.1:1880/" target="_self">
<label for="request"><strong>Please insert the input here:</strong></label><br>
<input type="text" id="request" name="input"><br>
<button v-on:click="getOverview($event)">Submit</button>
</form>
<h1 v-for="overview in overview">
{{overview}}
</h1>
</div>
Some problems here...
You're including Vue twice (https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js and https://unpkg.com/vue/dist/vue.js). Don't do that
You cannot use a v-for directive on your root Vue element
Your form is outside your Vue root so you won't be able to use v-on
Your submit button will submit the form normally. There's nothing stopping that from happening
Your input value is never used. You should try binding it to a data property
Change your HTML to
<div id="results">
<form action="http://127.0.0.1:1880/" #submit.prevent="getOverview">
<label for="request">
<strong>Please insert the input here:</strong>
</label>
<br>
<input type="text" id="request" name="input" v-model="input">
<br>
<button type="submit">Submit</button>
</form>
<h1 v-for="item in overview">
{{ item }}
</h1>
</div>
and in your JS, replace data with
data: () => ({
overview: [],
input: ''
})
Then you can use this.input if you ever need to get the value the user types in.
Here's an example using a placeholder API
new Vue({
el: "#results",
data: () => ({
overview: [],
input: ''
}),
methods: {
async getOverview ($event) {
let url = 'https://jsonplaceholder.typicode.com/users'
if (this.input) {
url += `/${encodeURIComponent(this.input)}`
}
try {
const { data: sub_regions } = await axios.get(url)
console.log('results data', sub_regions);
this.overview = Array.isArray(sub_regions) ? sub_regions : [ sub_regions ]
} catch (error) {
console.log(error);
this.overview = []
}
}
},
created() {
this.getOverview()
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<div id="results">
<form action="http://127.0.0.1:1880/" #submit.prevent="getOverview">
<label for="request">
<strong>Please insert the user ID here:</strong>
</label>
<br>
<input type="number" id="request" name="input" v-model.number="input">
<br>
<button type="submit">Submit</button>
</form>
<h1 v-for="item in overview">
{{ item.name }}
</h1>
</div>
Other notes:
Avoid using the same variable name for your array and iterable.
Bad - v-for="overview in overview"
Good - v-for="thing in things"
VueResource is long dead. Avoid using it or at least update to the latest version (1.5.1)

How to access form data nested inside divs (TypeScript)

In a following code I want to access user data written in a form each time user presses an enter key after typing some text data inside an input field in chat-form. Do you have any idea how can I access the following text-data using TypeScript? I have already tried with jQuery but none of the tested code seems to work. I am new to web-dev but very eager to learn new things.
<div id="chat-container">
<div id="search-container">
<input type="text" placeholder="search" />
</div>
<div id="conversation-list">
</div>
<div id="new-message-container">
+
</div>
<div id="chat-title">
</div>
<div id="chat-message-title">
</div>
<div id="chat-form">
<input id="chat-form" type="text" placeholder="Type a message!" />
</div>
</div>
first, you should use a semantic HTML by using form tag instead of div so u can use enter key to handle the submit action. second, it is not an appropriate way to duplicate an id for two different elements because id is a unique identifier for the element. finally here is a simple form and it might be helpful.
HTML:
<form id="my-form">
<input type="text" id="my-input" />
<button type="submit" id="submit-btn">send</button>
</form>
JS:
const formEl = document.getElementById("my-form") as HTMLFormElement;
const inputEl = formEl.querySelector("my-input") as HTMLInputElement;
const submitBtnEl = formEl.querySelector("submit-btn") as HTMLButtonElement;
formEl.addEventListener("submit", e => {
e.preventDefault();
// do what you want
});
inputEl.addEventListener("change", (e:Event|any) => {
console.log(e.target.value)
// do what you want
})
Before the answer: you have duplicated id="chat-form"
<div id="chat-form">
<input id="chat-form"type="text" placeholder="Type a message!"/>
</div>
Example
// select element
const elInput: HTMLInputElement = document.querySelector(`#chat-form-input`)
// add onkeypress listener
document.onkeypress = function (e: any) {
// use e.keyCode
if (e.key === 'Enter') {
// code for enter
console.log(elInput)
console.log(elInput.value)
}
}
<body>
<div id="chat-container">
<div id="search-container">
<input type="text" placeholder="search"/>
</div>
<div id="conversation-list">
</div>
<div id="new-message-container">
+
</div>
<div id="chat-title">
</div>
<div id="chat-message-title">
</div>
<div id="chat-form-container">
<input id="chat-form-input" type="text" placeholder="Type a message!"/>
</div>
</div>
</body>
You should try using a combination of JQuery.
Using this, you should put an id on the input element like so:
<input type="text" id="inputField" placeholder="search"/>
Then query the input field with JQuery. Best practice would suggest to store it in a local variable as well.
let inputFieldText = $("#inputField");
Then test for the value in the text field object as returned from JQuery.
if(inputFieldText.val()){
console.log(inputFieldText.val())
}
For reference, there is also a way to do so with document.getElementById("inputField"). Just link this function to a button that runs on pressing it (such as a "submit" button). Hope this helps!

Vue store slot data in parent component

I'm building a component which takes in multiple input fields using a slot, when the user submit's the form inside the parent component, I want to output the values of all the inputs.
index.html
<filter-form>
<input type="text" name="email" :value="form.email" />
</filter-form>
FilterForm.vue
<template>
<div>
<form
#submit.prevent="onSubmit"
>
<slot />
<div>
<button>
Submit
</button>
</div>
</form>
</div>
</template>
<script>
export default {
data () {
return {
form: {
email: 'test#email.com'
}
}
}
}
</script>
As you can see I'm referencing "form.email" inside index.html, which should populate the input with the data in the FilterForm component, however that's throwing this error
Property or method "form" is not defined on the instance but referenced during render
Which makes sense since the form data isn't available in the index.html file.
How can I use this system so that the data for the form is kept in the FilterForm component, but I can add any numbe of form inputs to the index.html file.
As #User 28 mentioned, you can take advantage of slots and scoped-slots to get this to work with an arbitrary number of fields like so:
<template>
<div id="app">
<FormWrapper :names="['name', 'country']" #submit="process($event)">
<template #default="{ form }">
<input name="name" type="text" v-model="form.name">
<input name="country" type="text" v-model="form.country">
</template>
</FormWrapper>
</div>
</template>
<script>
import FormWrapper from "./components/FormWrapper";
export default {
name: "App",
components: {
FormWrapper
},
methods: {
process(values) {
console.log(values);
}
}
};
</script>
Here, FormWrapper can nest arbitrary input fields. Some key points:
You need to provide names prop with some unique IDs for fields you care about.
When form inside FormWrapper is submitted, a submit event will be triggered with the values sent as an object.
Also note that we pass data for our slots in a form object and bind it to our inputs via v-model.
Here is the FormWrapper component:
<template>
<div class="form-wrapper">
<slot :form="form"></slot>
<div class="controls">
<button #click="submit()">Submit</button>
</div>
</div>
</template>
<script>
export default {
props: {
names: Array
},
data() {
return {
form: {}
};
},
created() {
for (const name of this.names) {
this.$set(this.form, name, "");
}
},
methods: {
submit() {
this.$emit("submit", this.form);
}
}
};
</script>
You can check https://codesandbox.io/s/so-form-wrapper-yxz0i for a working example.
Vue has a feature called Scoped Slots which might solve your problem.
<filter-form>
<template v-slot='slotProps'>
<input :value='slotProps.form.email' />
</template>
</filter-form>
and
<div>
<form #submit.prevent=''>
<slot :form='form'/>
<div>
<button>Submit</button>
</div>
</form>
</div>
Example

Is there an Aurelia equivalent to Angular 2's local template variables?

In Angular 2 you can create local template variables to more easily access elements in the html.
<input #name type="text">
<button (click)="submit(name.value)">Submit</button>
Is there an equivalent functionality to this in Aurelia?
Yes- it's the ref attribute.
Here's an example: https://gist.run?id=7d1140ba81542bf7a2609a0d09fcdea5
app.html
<template>
<input ref="name">
<button click.delegate="submit(name.value)">Click Me</button>
</template>
app.js
export class App {
submit(name) {
alert(name);
}
}
Use ref
<input type="text" ref="name" />
<button click.delegate="submit(name.value)">Submit</button>
http://aurelia.io/docs#/aurelia/framework/1.0.0-beta.1.1.4/doc/article/cheat-sheet/5

Categories

Resources