Suppose I had this code
<main>
<form>
<input type="text" v-model="name">
<button type="submit" #click="submit">
Submit From Vue Property
</button>
</form>
</main>
And this the Vue code.
new Vue({
el : 'main',
data : {
name : ''
},
methods : {
submit(){
}
}
})
how to submit to server from Vue data property instead? That i used in submit method.
( honestly, my actual code is much complicated but the problem is same. How to submit Vue data property instead? )
If you are looking for an ajax based solution, consider using a library called 'axios'. It lets you post/get data using urls much like jquery's get and post methods.
To use axios you need to first install axios using npm, npm install axios --save, import it using import axios from axios and use this in submit. The new code will look like below:
<main>
<form #submit.prevent="submit">
<input type="text" v-model="name">
<button type="submit">
Submit From Vue Property
</button>
</form>
</main>
new Vue({
el : 'main',
data : {
name : ''
},
methods : {
submit(){
axios.post('/your-url', {name: this.name})
.then(res => {
// do something with res
})
.catch(err => {// catch error});
}
}
})
Here you can submit total formdata using vue variables.you can make api's using axios.
<template>
<div>
<form #submit.prevent="submitform">
<input type="text" v-model="formdata.firstname">
<input type="text" v-model="formdata.lastname">
<input type="text" v-model="formdata.email">
<input type="text" v-model="formdata.password">
<button type="submit">
Submitform
</button>
</form>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'el',
data () {
return {
formdata:{ firstname: '', lastname: '', email: '', password: '' }
// this is formdata object to store form values
}
},
methods: {
submitform(){
axios.post('/url', { this.formdata })
.then(res => {
// response
})
.catch(err => {
// error
})
},
mounted () {
},
components: {
}
}
</script>
Related
Good day everyone, I'm trying to format the value that JSON brings me in currency, I saw some suggestions but I still can't convert the value.
This is how I've my code structured
<template>
...
<div class="currency-selection">
<input type="text" :value="conversionValue * cryptoQuantity " readonly />
...
<template>
<script>
export default {
name: 'CurrencySelect',
data: () => ({
conversionValue: 0,
cryptoQuantity: 1
}),
axios
.get(
"https://min-api.cryptocompare.com/data/price?fsym=btc&tsyms=COP"
)
.then((res) => {
this.conversionValue = res.data.COP;
})
.catch((e) => {
console.log(e);
});
}
Right now the value is 169057977.17 but I want it to be displayed like this: 169.057.977,17
You can use toLocaleString to format numbers acording to the language and region you define.
Use Number.toLocaleString('es-CO') get this: 169.057.977,17
See this for a list of supported locales
See this example
<script>
export default {
data() {
return {
conversionValue: 0,
cryptoQuantity: 1
}
},
async mounted () {
this.conversionValue = await fetch("https://min-api.cryptocompare.com/data/price?fsym=btc&tsyms=COP").then(raw => raw.json()).then(json => json.COP)
}
}
</script>
<template>
<input type="text" :value="(this.cryptoQuantity * this.conversionValue).toLocaleString('es-CO')"/>
</template>
My contact form is not sending the frontend user to my thank you page neither is it sending any information to me via the Sendgrid APi. The issue comes from the fact that I'm not sure how to turn the JSON object into a string and then straight back to an Object..... Or as you can see I have a hard time even framing my question. The goal would be to send the information to my email account using Sendgrid API.
The form is live here:
https://www.metsanotus.fi/yhteydenotto
The code is based 99% off these two tutorials:
https://oliverschmidt.dev/blog/adding-a-contact-form-to-a-static-site-with-netlify-functions/
https://dev.to/char_bone/using-netlify-lambda-functions-to-send-emails-from-a-gatsbyjs-site-3pnb
The code for the contact-page:
https://gist.github.com/otsolap/f05cd4e3a1a08794f61a6d5730abc695
import React, { useState } from "react";
import { graphql } from "gatsby"
import { RiSendPlane2Line } from "react-icons/ri";
import Layout from "../components/layout"
import SEO from "../components/seo"
export const pageQuery = graphql`
query ContactQuery($id: String!){
markdownRemark(id: { eq: $id }) {
id
html
excerpt(pruneLength: 140)
frontmatter {
title
}
}
site {
siteMetadata {
title
}
}
}
`
const Contact = ({ data }) => {
const { markdownRemark, site } = data // data.markdownRemark holds your post data
const { frontmatter, html } = markdownRemark
// input type hidden on netlifytä varten, jotta netlify tietää mikä lomake kyseessä.
// contact on meidän lomake, niin kaikki viestit löytyy contact-lomakkeen alta.
// honeypot=bot-field on botteja varten.
// p hidden pitää kohdan piilossa, mutta console.logilla sen löytää. ;-)
const [formState, setFormState] = useState({
name: '',
email: '',
phone: '',
subject: '',
message: '',
})
const handleChange = (e) => {
setFormState({
...formState,
[e.target.name]: e.target.value,
});
}
const handleSendEmail = async (event) => {
event.preventDefault();
try {
const response = await fetch("/.netlify/functions/contact-form-email", {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formState),
})
if (!response.ok) {
//EI 200 response
return
}
//all OK
} catch (event) {
//error
}
}
return (
<Layout className="contact-page">
<SEO
title={frontmatter.title}
description={frontmatter.title + " " + site.siteMetadata.title}
/>
<div className="wrapper">
<h1>{frontmatter.title}</h1>
<div className="description" dangerouslySetInnerHTML={{ __html: html }} />
<form className="contact-form"
action="/kiitos"
name="contact"
method="POST"
data-netlify="true"
value="contact"
data-netlify-honeypot="bot-field"
onSubmit={handleSendEmail}
>
<input type="hidden" name="form-name" value="contact" />
<p hidden><input name="bot-field" /></p>
<p>
<label><input
required
placeholder="Nimi *"
type="text"
name="name"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input required
placeholder="Sähköposti *"
type="email"
name="email"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input required
placeholder="Puhelin *"
type="number"
name="phone"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input placeholder="Aihe"
type="text"
name="subject"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><textarea
placeholder="Viesti"
name="message"
onChange={handleChange}
></textarea></label>
</p>
<p className="text-align-center">
<button className="button"
type="submit">
Lähetä<span className="icon -right"><RiSendPlane2Line />
</span>
</button>
</p>
</form>
</div>
</Layout>
)
}
export default Contact
The code for the serverless function:
https://gist.github.com/otsolap/e157b136aee040281f20ba87131014eb
require('dotenv').config();
const sgMail = require('#sendgrid/mail')
const {
SENDGRID_API_KEY,
METSAN_OTUS_NAME,
METSAN_OTUS_ADDRESS }
= process.env
sgMail.setApiKey(SENDGRID_API_KEY)
exports.handler = async (event, context, callback) => {
const payload = JSON.parse(event.body)
const { email, subject, message } = payload
const msg = {
to: METSAN_OTUS_ADDRESS,
name: METSAN_OTUS_NAME,
from: email,
subject: subject ? subject : 'Yhteydenotto lomakkeesta',
text: message,
};
try {
await sgMail.send(msg)
return {
statusCode: 200,
body: "Viesti lähetetty"
}
} catch (e) {
return {
body: e.message,
statusCode: 500,
}
}
};
When I keep the JSON.parse(body.event) this is the error it displays:
https://gist.github.com/otsolap/79830f6cf1e9b247c63c1f3f49c5286b
SyntaxError: Unexpected token u in JSON at position 0
If I change the line 13 of serverless-function.js from JSON.parse(event.body) to (for example) JSON.stringify(event.body) the error becomes this:
TypeError: Cannot destructure property 'email' of 'payload' as it is undefined.
So I guess my question is how should I formulate my serverless function so that the React object from UseState can become readable for my function?
I am pretty new to React and JS, and I am currently trying to create a component to integrate the antd form with modal so that I could utilize the form functionalities such as "validation".
Here is my code:
The function to post the request:
import baseUrl from "./baseUrl";
export async function _postSchoolRollOutRequest(schoolRollOutRequestForm) {
try {
const response = await fetch(
`${baseUrl}/feedbacks/request/schoolRollOutRequest`,
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(schoolRollOutRequestForm),
}
);
const data = await response.json();
console.log("Post school roll out form success!");
return data;
} catch (e) {
console.log("Post school roll out form failed!", e);
}
}
The component of integrating the form with modal:
import React, { useState } from "react";
import { Modal, Button, Form, Input, Radio } from "antd";
import { _postSchoolRollOutRequest } from "../../api/feedbacksApi";
import "./PopUp.scss";
export default (props) => {
const FormItem = Form.Item;
const [visible, setVisible] = useState(false);
const showModal = () => {
setVisible(true);
};
const handleOk = (schoolRollOutRequestForm) => {
_postSchoolRollOutRequest(schoolRollOutRequestForm);
setVisible(false);
};
const handleCancel = () => {
setVisible(false);
};
return (
<>
<Button type="primary" onClick={showModal}>
Roll-out My School!
</Button>
<Modal
destroyOnClose={true}
visible={visible}
title="Roll-out Request"
onCancel={handleCancel}
footer={[
<Button
block
key="submit"
type="primary"
onClick={(feedbackSubmission) =>
handleOk({
shoolName: feedbackSubmission.shoolName,
otherFeedback: feedbackSubmission.otherFeedback,
contact: feedbackSubmission.contact,
})
}
>
Roll-out My School!
</Button>,
]}
width={400}
>
<div className={"modal-body center"}>
<Form layout="vertical">
<Form.Item
label="Schools Name"
name="schoolName"
rules={[{ required: true }]}
>
{<Input type="text" label="schoolName" placeholder="UT Austin" />}
</Form.Item>
<FormItem
label="Any other requirements/feedback (optional)"
name="otherFeedback"
>
{<Input type="textarea" placeholder="abcd..." />}
</FormItem>
<FormItem label="How do we contact you? (optional)" name="contact">
{<Input type="text" placeholder="abcd#email.com" />}
</FormItem>
</Form>
</div>
</Modal>
</>
);
};
However, I encountered two problems that really confused me:
I think the button at the footer does not trigger the form's onFinish so that the form's validation does not work, I am wondering could I get any clue about the best practice for my situation?
I tried to fake a json for "handleOk" then later "_postSchoolRollOutRequest", but it seems like my backend get a request with an empty payload, could I get any insights about this problem as well?
Code Sandbox:
https://codesandbox.io/s/antdesignmodalform-stackoverflow-3yv4h?file=/index.js:920-3529
Firstly submit button should be inside form tag. If it is outside form tag then you need to make use of form attribute to trigger it.
In your case modal is always outside the form, so you have to link submit button with the form.
Here is how you can achieve it using ANT design.
Action Handler Code (if you are using redux then modify callback part as per your requirement)
export async function _postSchoolRollOutRequest(
schoolRollOutRequestForm,
callback
) {
const baseUrl = "http://testing.com";
console.log("form values", schoolRollOutRequestForm);
try {
const response = await fetch(
`${baseUrl}/feedbacks/request/schoolRollOutRequest`,
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(schoolRollOutRequestForm)
}
);
const data = await response.json();
console.log("Post school roll out form success!");
callback(response.status, data);
} catch (e) {
callback(e.status);
console.log("Post school roll out form failed!", e);
}
}
Form component
const FormModal = () => {
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [postData, setPostData] = useState({
loading: false,
error: false,
data: []
});
const onSubmit = (values) => {
setPostData({ ...postData, loading: true, error: false });
_postSchoolRollOutRequest(values, (status, data) => {
if (status === 200) {
form.resetFields();
setPostData({ ...postData, loading: false, data: data });
} else {
setPostData({
...postData,
loading: false,
error: true,
data: "Post school roll out form failed!"
});
}
});
};
return (
<>
<Button
type="primary"
onClick={() => {
setVisible(true);
}}
>
click to open form
</Button>
<Modal
visible={visible}
title="Post data"
okText="Submit"
cancelText="Cancel"
onCancel={() => {
setVisible(false);
}}
footer={[
<Button key="cancel" onClick={() => setVisible(false)}>
Cancel
</Button>,
<Button
key="submit"
type="primary"
loading={postData.loading}
onClick={() => {
form
.validateFields()
.then((values) => {
onSubmit(values);
})
.catch((info) => {
console.log("Validate Failed:", info);
});
}}
>
Submit
</Button>
]}
>
<Form
form={form}
layout="vertical"
name="form_in_modal"
initialValues={{
modifier: "public"
}}
>
<Form.Item
label="Schools Name"
name="schoolName"
rules={[
{
required: true,
message: ""
}
]}
>
<Input />
</Form.Item>
<Form.Item
label="Any other requirements/feedback (optional)"
name="otherFeedback"
>
<Input type="textarea" />
</Form.Item>
<Form.Item label="How do we contact you? (optional)" name="contact">
<Input />
</Form.Item>
{postData.error && (
<>
<br />
<span style={{ color: "red" }}>{postData.data}</span>
</>
)}
</Form>
</Modal>
</>
);
};
Here is a basic setup for what I would like to do:
HTML Side
test.html
<div id="app">
<my-comp temp="1" cat="{ name:'Geoff', age:3 }"></my-comp>
</div>
Vue Side
app.js:
import myComp from './components/myComp.vue'
app = new Vue({
el: "#app",
components: {
myComp
}
});
myComp.vue
<template>
<div v-html='template'>
</div>
</template>
<script>
export default {
props: [
'temp',
'cat'
],
data () {
temp1: `<input name="name" value="cat.name">
<input name="age" value="cat.age">`,
// other template
// ...
},
computed: {
template() {
return this.temp == 1 ? this.temp1 : this.temp2;
}
}
}
</script>
My problem is when I open the html file in the browser, I get:
cat.name
cat.age
appearing in the input. Technically, my form isn't responsive to existing data. How can I solve this?
In your test.html you have to change this:
<my-comp :temp="1" :cat="{ name:'Geoff', age:3 }"></my-comp>
The double dots have to added otherwise it will be interpreted as an string and not as an object.
With value you are on the right track. The only you have to change is this because you want to insert a variable into your 'string'
data() {
return {
temp1: `<input name="name" value="${this.cat.name}">
<input name="age" value="${this.cat.age}">`
}
}
Don't forget to add 'input type' as well.
I have a ReactJS page with three dropdown list, two of the dropdown list are displaying duplicate values. The values are being consumed from a json file. I researched using filter to remove the duplicates, but I'm unsure as to how I'm to apply it to my array when using React JS along with Fetch.
I created a function which employs the filter method, but I'm uncertain as to how I'm to implement it onto data: [], which contains the data consumed from the json file. This is the sample json file: https://api.myjson.com/bins/b1i6q
This is my code:
import React, { Component } from "react";
class Ast extends Component {
constructor() {
super();
this.state = {
data: [],
cfmRateFactor: "10"
};
} //end constructor
change = e => {
this.setState({
[e.target.name]: e.target.value
});
}; //end change
removeDups(array) {
return array.reduce((result, elem) => {
if (!result.some((e) => e.clientName === elem.clientName)) {
result.push(elem);
}
return result;
} , []);
}
componentWillMount() {
fetch("https://api.myjson.com/bins/b1i6q", {
method: "GET",
headers: {
Accept: "application/json",
"Content-type": "application/json"
}
/*body: JSON.stringify({
username: '{userName}',
password: '{password}'
})*/
}) /*end fetch */
.then(results => results.json())
.then(data => this.setState({ data: data }));
} //end life cycle
render() {
console.log(this.state.data);
return (
<div>
<div className="container">
<div className="astContainer">
<form>
<div>
<h2>Memeber Selection:</h2>
{["clientName", "siteName", "segmentName"].map(key => (
<div className="dropdown-padding">
<select key={key} className="custom-select">
{this.state.data.map(({ [key]: value }) => (
<option key={value}>{value}</option>
))}
</select>
</div>
))}
</div>
<div className="txt_cfm">
<label for="example-text-input">Modify CFM Rate Factor:</label>
<input
class="form-control"
type="textbox"
id="cfmRateFactor"
name="cfmRateFactor"
value={this.state.cfmRateFactor}
onChange={e => this.change(e)}
/>
</div>
<div>
<div>
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
</div>
</form>
</div>
</div>
</div>
);
}
}
export default Ast;
Could I please get some help with this? I'm still very new to using React JS.
You could use Map, it's a data structure for keeping key-value pairs. It will give you best performance for large data.
removeDuplicates(arr) {
const map = new Map();
arr.forEach(v => map.set(v.abc_buildingid, v)) // having `abc_buildingid` is always unique
return [...map.values()];
}
// this hook is better to start fetching data than componentWillMount
componentDidMount() {
fetch("https://api.myjson.com/bins/b1i6q", {
method: "GET",
headers: {
Accept: "application/json",
"Content-type": "application/json"
}
})
.then(results => results.json())
.then(data => this.setState({ data: this.removeDuplicates(data) })); // use the defined method
} //end life cycle
filter won't solve your problem. But reduce will.
You could have the following :
function removeDups(array) {
return array.reduce((result, elem) => {
if (!result.some((e) => e.abc_buildingid === element.abc_buildingid)) {
result.push(elem);
}
return result;
} , []);
}