how to reset form data after successfull axios post request - forms

I have modalform component made using Alpine js and axios for POST request.
But I cannot understand few things:
How to reset form data after succesfull POST request.
I see error in console TypeError: this.resetFields is not a function
How to get errors to show them for the user if POST request is failed due to validation errors with 422 status code.
I want to bind errors.message to AlpineJs variable errors and then show it on the webpage using <p x-text="errors" class="text-red-600"></p>, but this.errors = error.message; seems not working, because in AlpineJS devtools in Chrome errors variable doesn't change.
function modalform() {
return {
mailTooltip: false,
instagramTooltip: false,
openModal: false,
formData: {
name: '',
phone: '',
email: '',
address: '',
message: '',
_token: '{{ csrf_token() }}'
},
message: '',
errors: '',
loading: false,
sent: false,
buttonLabel: 'Send',
resetFields() {
this.formData.name = '',
this.formData.phone = '',
this.formData.email = '',
this.formData.address = '',
this.formData.message = ''
},
submitData() {
this.buttonLabel = 'Sending...';
this.loading = true;
this.message = '';
axios.post('/modalform', this.formData)
.then(function (response) {
console.log(response);
this.resetFields();
this.message = response.data.name;
})
.catch(function (error) {
console.log(error);
this.errors = error.message;
});
},
}
}
```

You have a scoping issue. If you use the old function(response){...} style, then this refers to the object it was called on (axios). However is you replace it with the arrow function, then this will refer to the first non-arrow function object, in this case: the Alpine.js component.
axios.post('/modalform', this.formData)
.then((response) => {
console.log(response);
this.resetFields();
this.message = response.data.name;
})
.catch((error) => {
console.log(error);
this.errors = error.message;
});

Related

What does it mean if a post with status 200 is left waiting?

I am doing a POST to an enpoint to authenticate users. The endopoint is "/user/login". I make a post and receive status code 200 but the Postman, and also my client, are waiting for the RES object that does not arrive.
This is a screenshot of the API call through Postman:
This is controler in server side:
router.post(
'/user/login',
passport.authenticate('local'),
UserCtrl.getLogin,
)
getLogin = (req, res, next) => {
console.log("req: ", req.body)
console.log('logged in', req.user);
var userInfo = {
username: req.user.username
};
res.json(userInfo)
}
The console prints the lines in the controller, and the user is effectively authenticated, for example:
req: { username: 'fedex', password: 'fedex' }
logged in {
_id: new ObjectId("62a8b00f468c563699d7dfc2"),
username: 'fedex',
password: '$2a$10$cdbh0oCBNpHxxwebsvArLOAFwetVAh5LTnQwk1Lg9kjWkjAWhfxym',
__v: 0
}
probably the problem is in the invocation of the local passport strategy, but I only do the standard:
const strategy = new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, (err, user) => {
if (err) {
return done(err)
}
if (!user) {
return done(null, false, { message: 'Incorrect username' })
}
if (!user.checkPassword(password)) {
return done(null, false, { message: 'Incorrect password' })
}
return done(null, user)
})
}
)
EDITED: If I remove the middleware where the passport.authenticate('local') is invoked, and incorporate the authentication functionality directly in the controller, it works. But what is wrong with calling passport in the route?
BEFORE (does not work):
router.post(
'/user/login',
passport.authenticate('local'),
UserCtrl.getLogin
)
AFTER (adding passport authentication inside the controller, it work)
router.post(
'/user/login',
UserCtrl.getLogin
)

Mongodb .post unable to add data to the collection

I am trying to take user input and then add a drug(medicine) to MongoDB. But it is not working and I am getting the error "Add proper parameter first". The user input should be patient name, drug name, dosage, frequency, adherence, and reason for not taking medicine. Please help!
app.post("/add-drug", (req, res) => {
try {
if (req.body && req.body.patient_name && req.body.drug_name && req.body.dosage && req.body.frequency && req.body.adherence && req.body.reason) {
let new_drug = new drug();
new_drug.patient_name = req.body.patient_name
new_drug.drug_name = req.body.drug_name;
new_drug.dosage = req.body.dosage;
new_drug.frequency = req.body.frequency;
new_drug.adherence = req.body.adherence;
new_drug.reason = req.body.reason;
new_drug.user_id = req.user.id;
new_drug.save((err, data) => {
if (err) {
res.status(400).json({
errorMessage: err,
status: false
});
} else {
res.status(200).json({
status: true,
title: 'Drug Added successfully.'
});
}
});
} else {
res.status(400).json({
errorMessage: 'Add proper parameter first!',
status: false
});
}
} catch (e) {
res.status(400).json({
errorMessage: 'Something went wrong!',
status: false
});
}
});
The model file looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
drugSchema = new Schema( {
patient_name: String,
drug_name: String,
dosage: Number,
frequency: Number,
adherence: Number,
reason: String,
user_id: Schema.ObjectId,
}),
drug = mongoose.model('drug', drugSchema);
module.exports = drug;
it is supposed to be <field>:<value> inside your app.post method, not <field>=<value>
The new_drug.save() method is asynchronous, so it returns a promise that you can await on:
app.post("/add-drug", async(req, res) => {
//...
await new_drug.save();
})

express-validator showing undefined for defined values

I'm sending data to server using fetch:
const post = async(data)=>{
console.log(data)
const response = await fetch("/comments", {
method: "POST",
body:JSON.stringify(data)
});
return response.json();
};
data is console logged, it's a standard object with keys and values. And it arrives to server, same keys and values.
On the server I run this express-validation for sanitizing:
router.use(express.json());
router.post("/",
body("email").isEmail().normalizeEmail(),
body("name").trim().escape(),
body("msg").not().isEmpty().trim().escape(),
(req,res,next)=>{
const errors = validationResult(req);
console.log(errors);
if (!errors.isEmpty()) { res.status(422).json({ errors: errors.array() }); return};
try{
saveComment(req.body, (err,doc) => {
err? next(createError(500, "Couldn't save the document. Try again.")):
res.json({msg:"saved"});
});
} catch(e) {
next(createError(500, ISE));
}
});
And what I get is:
Result {
formatter: [Function: formatter],
errors: [
{
value: undefined,
msg: 'Invalid value',
param: 'email',
location: 'body'
},
{
value: undefined,
msg: 'Invalid value',
param: 'msg',
location: 'body'
}
]
}
POST /comments 422 17.821 ms - 126
What is the error?
Set header in the fetch function:
headers: {"Content-Type":"application/json"}

My POST request works on Postman but not with axios

I have a nuxt project deployed on Netlify and now I want to add a newsletter (add a subscriber to my audience on Mailchimp). To achieve that, I've opted to use the AWS serverless lambda functions. To be honest, it's the first time that i've heard about serverless functions. I found this tutorial https://hashinteractive.com/blog/nuxt-js-mailchimp-integration-add-contact-to-list/ and at the end, i've decided to make a test on Postman. I've made a post to http://localhost:8888/.netlify/functions/subscribe and it worked. But when I try the same thing with axios I get the error 405 (method not allowed).
Newsletter.vue
<form #submit.prevent='submitNewsletter' class="newsletter__form" >
<input type="email" placeholder="E-mail" class="newsletter__form-input" v-model="email">
<button class="newsletter__form-button" type="submit">Subscribe</button>
</form>
</div>
</template>
<script>
import axios from 'axios';
export default {
data(){
return{
email: ''
}
},
methods:{
submitNewsletter(){
axios.post('http://localhost:8888/.netlify/functions/subscribe', { email: this.email}, {
headers: {
methods: 'POST',
'Content-Type':'application/json'
}
})
.then(function (response) {
console.log(response);
}).
catch((error) =>{
console.log('The error:' + error)
})
this.$toasted.success("Thank you for your subscription !!!", {
theme: "toasted-primary",
position: "top-left",
containerClass: 'myContainer',
fitToScreen: true,
fullWidth: true,
duration : 5000
});
}
}
}
</script>
functions > subscribe > subscribe.js
const fetch = require('node-fetch');
const base64 = require('base-64');
exports.handler = async (event, context) => {
// Only allow POST
if (event.httpMethod !== 'POST') {
return { statusCode: 405, body: 'Method Not Allowed' };
}
const errorGen = msg => {
return { statusCode: 500, body: msg };
};
try {
const { email } = JSON.parse(event.body);
console.log(email);
if (!email) {
return errorGen('Missing Email');
}
const subscriber = {
email_address: email,
status: 'subscribed',
};
console.log(subscriber);
console.log(JSON.stringify(subscriber));
const creds = `blooming-thoughts:${process.env.MAILCHIMPS_API_KEY}`;
const response = await fetch(`https://us20.api.mailchimp.com/3.0/lists/${process.env.AUDIENCE_ID}/members/`, {
method: 'POST',
headers: {
Accept: '*/*',
'Content-Type': 'application/json',
Authorization: `Basic ${base64.encode(creds)}`, },
body: JSON.stringify(subscriber),
});
const data = await response.json();
if (!response.ok) {
// NOT res.status >= 200 && res.status < 300
return { statusCode: data.status, body: data.detail };
}
return {
statusCode: 200,
body: JSON.stringify({ msg: "You've signed up to the mailing list!", detail: data, }),
};
} catch (err) {
console.log(err); // output to netlify function log
return {
statusCode: 500,
body: JSON.stringify({ msg: err.message }),
};
}
};
My netlify.toml
[build]
publish = "dist"
functions = 'functions'
I've made a push to my repository and netlify built without any error, but when I try to add a newsletter from my site nothing happens.
I've solved my problem. If you're having trouble like I was, follow these steps:
Create a folder called functions in your root directory, then create a index.js (the file name is up to you).
Create a file called netlify.toml and add the following code :
[build]
functions = "functions"
Then, inside your index.js goes the code that will communicate with your API
On the vue component, make a post request to the <your-site>/.netlify/functions/index . You can find the endpoint going to functions on netlify dashbord.
Don't forget to register your env variables on Netlify (Build & Deploy) and that's it.

Stub action2 helper on testing action2 controller routes response supertest

I have a project on Sails.js 1
I try to use TDD on development, so I've added route testing. To prevent real API call in helpers I've mocked them via sinon
So I can successfully pass tests with this code
action2 controller code
module.exports = {
friendlyName: 'Some action',
description: '',
inputs: {
requiredParam: {
example: 'some_value',
required: true,
type: 'string',
}
},
exits: {
someError: {
description: 'Handles some error happens in controller',
message: 'Some error handled in controller',
}
},
fn: async function (inputs, exits) {
const someProcesses = await sails.helpers.someHelper(inputs.requiredParam);
if (someProcesses === 'someError') {
exits.someError(someProcesses);
} else {
exits.success(someProcesses);
}
}
};
Helper code
module.exports = {
friendlyName: 'Some helper',
description: '',
inputs: {
requiredParam: {
example: 'some_value',
required: true,
type: 'string',
}
},
exits: {
someError: {
description: 'Just some error happens in workflow',
message: 'Some error happens!',
}
},
fn: async function (inputs, exits) {
// All done.
return inputs.requiredParam === 'isError' ? exits.success('someError') : exits.success('someProcessedValue');
}
};
test code
const request = require('supertest');
const {createSandbox} = require('sinon');
describe('GET /some-page/some-action', () => {
before(() => {
this.sandbox = createSandbox();
this.sandbox.stub(sails.helpers, 'someHelper')
.withArgs('some_value').returns('someProcessedValue')
.withArgs('isError').returns('someError');
});
after(() => {
this.sandbox.restore();
});
it('should response OK', async () => {
await request(sails.hooks.http.app)
.get('/some-page/some-action')
.query({requiredParam: 'some_value'})
.expect(200);
});
it('should response with error', async () => {
await request(sails.hooks.http.app)
.get('/some-page/some-action')
.query({requiredParam: 'isError'})
.expect(500);
});
});
Then I've read on the official doc helper page that we should use exits and intercept to correctly handle errors from helpers on Sails.js 1.
So I've rewritten my action2 and helper to its usage and got next
Action2 controller with action2 intercept handling
module.exports = {
friendlyName: 'Some action',
description: '',
inputs: {
requiredParam: {
example: 'some_value',
required: true,
type: 'string',
}
},
exits: {
someError: {
description: 'Handles some error happens in controller',
message: 'Some error handled in controller',
}
},
fn: async function (inputs, exits) {
const someProcesses = await sails.helpers.someHelper(inputs.requiredParam)
.intercept('someError', exits.someError);// Error happens here
return exits.success(someProcesses);
}
};
Helper with exit triggering
I noticed this is problematic to test action2 controllers with preventing real helpers calls, cause when we stub helper methods using we got an error on next chained call but without these calls we can't user recommended error handling.
While I haven't used chained machine methods (tolerate, intercept etc) all test passes successfully, but when I affect it, I got an error.
Error
error: Sending 500 ("Server Error") response:
TypeError: sails.helpers.someHelper(...).intercept is not a function
I've prepared a repo on GitHub if someone wants to try some idea.
Repo tags
correct-test-result-without-chained-helper-methods - tests without reverse
broken-tests-with-chained-methods - broken tests.
Here is a related question but it is for Sails.js 0.12.14-
Any idea how to avoid this problem? I will appreciate any answer.