Vuelidate display error messages based on server side response? - javascript

Is there a way to create a validation on an input field based on a server side response with a vuelidate helper? I used a different approach by creating some data fields and then in my form submit check what code is being returned from the server and then displaying the error message from the data. This "kind of" works but now when the user types in the field again the error message remains until the server returns a success code.
My end result / goal would be just display the same error message for each response scenario and when the error is showing from server code responses and user begins to type again the error message is removed until another request is made.
<div class="form-field">
<label for="">
Enter your patient ID
</label>
<input type="text" class="form-input" name="isPatient" id="isPatient" v-model="$v.formData.isPatient.$model" />
<label v-if="($v.formData.isPatient.$dirty && !$v.formData.isPatient.validInput) || invalidPatient"
class="error error--invalidIsPatient">
We're sorry, this patient does not exist.
</label>
</div>
<div class="form-field">
<label for="">
Enter your Childs ID
</label>
<input type="text" class="form-input" name="isChild" id="isChild" v-model="$v.formData.isChild.$model" />
<label v-if="($v.formData.isChild.$dirty && !$v.formData.isChild.validInput) || invalidChild"
class="error error--invalidIsChild">
We're sorry, this child does not exist.
</label>
</div>
<script>
import { validationMixin } from 'vuelidate'
const { required } = require('vuelidate/lib/validators')
const VueScrollTo = require('vue-scrollto')
export default {
name: 'ActivateCard',
mixins: [validationMixin],
data() {
return {
formData: {
isPatient: null,
isChild: null
},
showDemographics: false,
showIdErrors: false,
showConfirmation: false,
invalidPatient: false,
invalidChild: false
}
},
validations: {
formData: {
isPatient: {
validInput: (value, vm) => {
const isValidValue = value != null && value.trim().length
const altValueIsValid = vm.isChild !== null && vm.isChild.trim().length
return isValidValue ? true : altValueIsValid
}
},
isChild: {
validInput: (value, vm) => {
const isValidValue = value !== null && value.trim().length
const altValueIsValid = vm.isPatient !== null && vm.isPatient.trim().length
return isValidValue ? true : altValueIsValid
}
}
}
},
methods: {
submitCardId() {
this.$v.$reset()
this.$v.$touch()
if (!this.$v.$invalid) {
const formData = new FormData()
formData.append('method', 'activate')
formData.append('isPatient', this.formData.isPatient)
formData.append('isChild', this.formData.isChild)
this.$services
.post('', formData)
.then(response => {
const responseCode = response.data.trim()
const responseSuccess = responseCode === 'success'
const responseHdBad = responseCode === 'hd-bad'
const responseCardBad = responseCode === 'card-bad'
const responseBothBad = responseCode === 'both-bad'
console.log(`activate response: ${responseCode}`)
if (responseSuccess) {
this.showDemographics = true
this.invalidPatient = false
this.invalidChild = false
}
if (responseBothBad) {
this.invalidPatient = true
this.invalidChild = true
}
if (responseHdBad) {
this.invalidPatient = true
}
if (responseCardBad) {
this.invalidChild = true
}
})
.catch(err => {
console.log(err + ' Activate Card Error')
})
}
}
}
}
</script>

Related

preventDefault unless form is successfully submitted

I have a user form to submit blog posts. I want to display errors on the form if users do not enter acceptable data or miss a field. I used event.preventDefault(); to keep the page from reloading when they push submit. Everything works how I want it to, accept I want the page to reload after the form is successfully submitted. as of right now, the data from the form will submit, but it will not reload the page. How can I get it so the page and form reload as soon as the form successfully submits, but not when there are errors?
Here is my jsx
import React from 'react'
import fireIconImage from '../images/fireIcon.png'
import FireIcon from './FireIcon'
export default function BlogPostForm () {
const [formState, setFormState] = React.useState({ flaire: '', title: '', text: '', fireLevel: ''});
const [isHovered, setIsHovered] = React.useState();
const [isLit, setIsLit] = React.useState();
const [formErrors, setFormErrors] = React.useState({});
/*need to start implementing the validation states,
/*will need an errorState object with a specified error for each field*/
/*handleChange for input fields*/
function handleChange(e) {
const { name, value } = e.target;
setFormState({...formState, [name]: value})
}
/*functions for fire icon handling*/
function handleMouseOver(e) {
setIsHovered(e.target.id);
}
function handleMouseLeave(e) {
setIsHovered();
}
function handleFireIconClick(e) {
setIsLit(e.target.id);
setFormState((prevFormState) => ({...prevFormState, fireLevel: e.target.id}))
}
function handleFireIconClass(fireLevel) {
const classNames = ['fireIcon']
classNames.push(`fireIcon${fireLevel}`)
if (isHovered >= fireLevel) {
classNames.push('isHeld')
}
if (isLit >= fireLevel) {
classNames.push('isLit')
}
return classNames.join(' ');
}
/*render 5 fireIcons */
const fireIconsArray = [];
for (let i = 0; i < 5; i++) {
fireIconsArray.push(
<FireIcon
onClick={handleFireIconClick}
onMouseLeave={handleMouseLeave}
onMouseOver={handleMouseOver}
className={handleFireIconClass(i+1)}
src={fireIconImage}
alt="fire icon"
id={i+1}
key={i+1}
/>
)
}
/*submit function*/
function validate(values) {
const errors = {}
if(!values.flaire) {
errors.flaire = "Flaire is required!"
}
if(!values.title) {
errors.title = "Title is required!"
}
if(!values.text) {
errors.text = "Text is required!"
}
if(!values.fireLevel) {
errors.fireLevel = "Select a fire level!"
}
return errors;
}
function submitForm(event) {
event.preventDefault();
const errors = setFormErrors(validate(formState));
if (errors) {
console.log(errors)
return;
}
/*post to database*/
const data = formState;
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}
fetch('http://localhost:8000', options);
}
/*blogPostForm jsx*/
return (
<form className="postForm">
<h1 className="postFormHeader">Create a blog post!</h1>
<select
required
className="flaireSelect"
name="flaire"
value={formState.flaire}
onChange={handleChange}>
<option disabled={true} value="">Choose a flaire</option>
<option value="JavaScript">JavaScript</option>
<option value="CSS">CSS</option>
<option value="HTML">HTML</option>
<option value="REACT">REACT</option>
<option value="BACKEND">BACKEND</option>
</select>
{formErrors.flaire && <p className="inputError inputErrorCenter">{ formErrors.flaire }</p> }
<input
value={formState.title}
onChange={handleChange}
className="titleBox"
placeholder="title"
type="text"
id="title"
name="title"
/>
{formErrors.title && <p className="inputError">{ formErrors.title }</p> }
<textarea
value={formState.text}
onChange={handleChange}
className="textBox"
placeholder="text"
type="text"
id="blogPost"
name="text"
/>
{formErrors.text && <p className="inputError">{ formErrors.text }</p> }
<div className="fireIconContainer">
{fireIconsArray}
</div>
{formErrors.fireLevel && <p className="inputError inputErrorCenter">{ formErrors.fireLevel }</p> }
<div className="blogPostFormButtonContainer">
<button className="blogPostSubmit" type="submit" onClick={submitForm}>SUBMIT</button>
<button className="blogPostCancel" type="submit">CANCEL</button>
</div>
</form>
)
}
You can check the length of the Object that validate() returns to check if there are errors, and if there are none, then you can continue, like so:
function submitForm(event) {
if (!Object.keys(validate(formState)).length === 0) {
event.preventDefault();
console.log(errors);
return;
}
// ...
}
Or place the preventDefault into your errors check, like so:
if (errors) {
event.preventDefault();
console.log(errors);
return;
}
Believe it or not, preventDefault() is not limited to an event handler scope.
If you want to reload the page after a successful save, then after fetch() call .then() & then call window.location.reload() to reload the page
As an example:
function submitForm(event)
{
event.preventDefault();
const errors = setFormErrors(validate(formState));
if (errors)
{
console.log(errors)
return;
}
/*post to database*/
const data = formState;
const options = {
method: 'POST',
headers:
{
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}
fetch('http://localhost:8000', options)
.then((response) => window.location.reload()); // You might want to check the status code or response.

How to submit empty value and make it send None as a string react

I am trying to send an empty value and when I submit it, it send "None" to the data.
Here is my code base:
const [addLoanClause, setAddLoanClause] = useState("");
const handleSubmit = () => {
if (id) {
var loanProposalDetailsUpdateObject = {
...
addLoanClause: addLoanClause,
};
if (dataChanged(loanProposalDetailsUpdateObject)) {
updateUserLoanProposalRequest({
loanProposalDetails: loanProposalDetailsUpdateObject,
}).then(() => {
routeToNextPage(isUserLoanRequestInitiator, router, id);
});
}
else {
routeToNextPage(isUserLoanRequestInitiator, router, id);
}
} else {
props
.createUserLoanRequest({
requestType: transactionType,
status: "draft",
loanProposalDetails: {
...
addLoanClause: addLoanClause,
},
})
.then(data => {
routeToNextPage(isUserLoanRequestInitiator, router, data.id);
});
}
};
<DynamicWidthInput
id="addLoanClause"
value={addLoanClause}
type="textarea"
placeholder="1000 characters"
error={showErrors && getError("addLoanClause")}
onChange={e =>
handleDynamicStateChange(e, setAddLoanClause)
}
size={"xxl"}
rows="5"
/>
How can I achieve it if I want to send empty value in textarea and it will automatically know to send string "None" to the data?
You could define your value to be sent using a ternary referencing the length of the input:
const output = addLoanClause.length > 0 ? addLoanClause : 'None'
So if the length of the input is greater than zero, use the input. Else, use 'None'

How to set default value in Tagify

I have an autocomplite input on my page, but i want to show some values before user begin typing
I read Tagify documentation but find nothing about it
I tried use tagTextProp but it not works
When i set value attribute on my original input then autocomplite stop working
my input on the page
<div class="form-control">
<input id="DetailsAddress" name="address" type="text" class="form-control__control" data-action="form-control" autocomplete="off">
<div class="form-control__label"><?php EP_Lng::_e('Address'); ?></div>
</div>
<div class="form__alert form__alert_error" id="field_address" style="display:none;"></div>
my Tagify js code
cityAutocomplete(input = null) {
input = input || document.getElementById('city_autocomplete')
let url = input.dataset.url || en4.core.baseUrl + 'pets/ajax/city';
let whitelist = input.value ? JSON.parse(input.value) : [];
let tagify = new Tagify(input, {
enforceWhitelist: true,
whitelist: whitelist,
mode: 'select',
value =[{"value":"bar"}],
tagTextProp: 'value',
});
let controller;
tagify.on('input', onInput)
function onInput( e ) {
var value = e.detail.value;
tagify.settings.whitelist.length = 0; // reset the whitelist
controller && controller.abort();
controller = new AbortController();
// show loading animation and hide the suggestions dropdown
tagify.loading(true).dropdown.hide.call(tagify)
let data = new FormData();
data.append('text', value);
fetch(url, {
signal: controller.signal,
method: 'POST',
body: data
})
.then(response => response.json())
.then(whitelist => {
whitelist = whitelist.map(item => {
return {
value: item.label,
id: item.id
}
})
// update inwhitelist Array in-place
tagify.settings.whitelist.splice(0, whitelist.length, ...whitelist)
tagify.loading(false).dropdown.show.call(tagify, value); // render the suggestions dropdown
})
}
tagify.on('change', onChange)
function onChange(e) {
// outputs a String
let location_id = document.getElementById("location_id");
if (!location_id) {
console.warn('Hidden field location_id not found')
return;
}
if (!e.detail.value) {
location_id.value = '';
} else {
let value = JSON.parse(e.detail.value);
location_id.value = value[0].id;
}
}
return tagify
}
How I use it
const addressInput = document.getElementById('DetailsAddress')
this.cityAutocomplete(addressInput)

Javascript array filter two searchbox

How to filter array values dynamically with two string (searchboxes)? Here's what I've tried so far:
if (!!this.searchCompany.toLowerCase() || !!this.searchName.toLowerCase()) {
this.filter = true
this.newval = this.list.filter(post => {
if (!!this.searchCompany.toLowerCase()) {
return post.profile.company ? post.profile.company.toLowerCase().includes(this.searchCompany.toLowerCase()) : null
} else if (!!this.searchName.toLowerCase()) {
return post.profile.full_name.toLowerCase().includes(this.searchName.toLowerCase())
} else {
return post
}
})
this.searchCompany and this.searchName are the searchboxes in my form.
The array content of this.list
UPD:
Here is your condition checking
if(!!this.searchCompany.toLowerCase())
It does not check whether the value is presented and in lower case. Firstly it will be transformed to lower case by String method and then cast to boolean type. As we know, empty string casts to boolean FALSE and any non empty string to TRUE. Moreover, you can get TypeError in case that searchCompany property is not presented in this.
Here small example snippet how you can search in array of objects
const posts = [{
company: 'Coca-Cola',
name: 'Rocket'
},
{
company: 'Pepsi-Cola',
name: 'Groot'
}
]
let form = document.forms['search-form']
let resultBox = document.querySelector('#result-box')
let searchButton = document.querySelector('#search')
searchButton.addEventListener('click', doSearch, false)
function searchPost(parameter, searchString) {
return posts.find(post => post[parameter].toLowerCase().includes(searchString.toLowerCase()))
}
function isFormEmpty() {
return [...form.children].filter(e => e.type === 'text').reduce((r, c) => r && !c.value.length, true)
}
function doSearch() {
if (isFormEmpty(form)) {
e.preventDefault()
return false
}
let searchNameEl = form.querySelector('[name="searchName"]')
let searchCompanyEl = form.querySelector('[name="searchCompany"]')
let searchParam = searchCompanyEl.value.length ? 'company' : 'name'
let searchText = searchCompanyEl.value.length ? searchCompanyEl.value : searchNameEl.value
let post = searchPost(searchParam, searchText)
resultBox.textContent = JSON.stringify(post)
}
form {
display: block;
}
.result {
margin-top: 10px;
}
<form id="search-form">
<label>Search company</label>
<input type="text" name="searchCompany" />
<label>Search name</label>
<input type="text" name="searchName" />
<button type="button" id="search">Search</button>
</form>
<div class="result">
<pre id="result-box"></pre>
</div>

Using Perl with ReactJS

What I am trying to do is run a Perl script with arguments from ReactJS and return results. For my purpose, the same could be achieved if I could run console commands through ReactJS. Eventually, I plan to make this into an electronic app. Any suggested methods? Thank you.
Keep your Perl script hosted at a web API, for instance, http://www.example.com/your/perl/script.pl. Then, in your React code, you would just do the following:
fetch('http://www.example.com/your/perl/script.pl', {
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
'method':'POST',
'body':JSON.stringify({'someargument':'123'}),
})
.then((response) => response.json())
.then((responseJson)=>{
console.info("Response?");
console.info(responseJson);
});
Your Perl script will need to have a JSON parser (I recommend CPAN's JSON lib). Then you will have communication from the front-end (ReactJS) to the back-end (your Perl script). Let the fun begin. =)
If you want to know more about Fetch(): https://scotch.io/tutorials/how-to-use-the-javascript-fetch-api-to-get-data
If you are trying to insert data using perl you can try following code:
In insert.js import following file:
import React, { Component } from 'react';
import './App.css';
export default class Insert extends React.Component {
constructor() {
super();
this.state = {
fields: {},
json_response : []
}
this.instantform= this.instantform.bind(this);
this.change=this.change.bind(this);
}
change= (e)=>{
let fields= this.state.fields;
fields[e.target.name] = e.target.value;
//alert (fields);
this.setState({
fields
});
};
renderListing() {
let recordList = []
this.state.json_response.map(record => {
alert(record.Usernamename);
return recordList.push(
<tr>
<td>{record.Usernamename}</td>
<td>{record.password}</td>
</tr>
)
})
return recordList;
}
Validate your page:
handleValidation(){
var pattern;
let fields = this.state.fields;
let errors = {};
let formIsValid = true;
if (!fields["channel_id"]) {
formIsValid = false;
errors["channel_id"] = "*Please enter your channel_id";
alert('Please enter your channel_id');
}
if (typeof fields["channel_id"] !== "undefined") {
pattern = new RegExp(/^-?\d*$/);
if (!pattern.test(fields["channel_id"])) {
formIsValid = false;
errors["channel_id"] = "*Please enter valid channel id.";
alert('Please enter valid channel id');
}
}
if (!fields["Username"]) {
formIsValid = false;
errors["Username"] = "*Please enter your Username.";
alert('Please enter your Username.');
}
if (typeof fields["Username"] !== "undefined") {
if (!fields["Username"].match(/^[a-zA-Z ]*$/)) {
formIsValid = false;
errors["Username"] = "*Please enter alphabet characters only.";
alert('Please enter alphabet characters only.');
}
}
if (!fields["Hotel_id"]) {
formIsValid = false;
errors["Hotel_id"] = "*Please enter your Hotel_id";
alert('Please enter your Hotel_id');
}
if (typeof fields["Hotel_id"] !== "undefined") {
//regular expression for email validation
//var pattern = new RegExp(/^-?\d*$/);
if (!fields["Hotel_id"].match(/^-?\d*$/)) {
formIsValid = false;
errors["Hotel_id"] = "*Please enter valid Hotel - id.";
alert('Please enter valid Hotel - id.');
}
}
if (!fields["password"]) {
formIsValid = false;
errors["password"] = "*Please enter your password.";
alert('*Please enter your password.');
}
if (typeof fields["password"] !== "undefined") {
if (!fields["password"].match(/((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##$%]).{6,20})/)) {
formIsValid = false;
errors["password"] = "*Please enter secure and strong password.";
alert('*Please enter secure and strong password');
}
}
this.setState({
errors: errors
});
return formIsValid;
}
Form Onlick method:
instantform =(e)=>{
e.preventDefault();
if(this.handleValidation())
{
//alert("Sucess");
var fields = this.state.fields;
this.setState({ loading: true, disabled: true }, () =>
{
//console.log(fields);
fetch('http://ubuntu:90/common-cgi/trainee/krunal/my-app/src/database/insert.pl',
//fetch('http://192.168.0.50:3000/myfirst_app/src/testing.php',
{
method: 'POST',
headers:
{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(fields)
}).then(res => {
//.then(res => res.text()).then(text => {
alert("Success");
// this.setState({
// json_response: json_response
//})
//JSON.stringify(json_response);
//alert(json_response.Username);
//fields["Username"] = "";
//fields["lastname"] = "";
//fields["email"] = "";
//fields["message"] = "";
//this.setState({fields:fields});
}).catch((error) =>
{
console.error(error.toString());
//console.warn(error);
this.setState({ loading: false, disabled: false });
});
});
}
}
Render:
render() {
return (
<div className="container">
<center>
<div className="keyformwrap">
<form method="post" name="instantform" onSubmit={this.instantform}>
<br />
<label>User name</label>
<input
type="text"
id="Username"
name ="Username"
placeholder="Your User name..."
value = {this.state.fields.Username}
onChange ={e => this.change(e)}
/>
<label>User Lastname</label>
<input type="text" id="Fullname"
name ="Fullname"
placeholder="Your Full name.."
value = {this.state.fields.Fullname}
onChange ={e => this.change(e)}
/>
<label>Department</label>
<input type="text" id="department"
name ="department"
placeholder="Your department.."
value = {this.state.fields.department}
onChange ={e => this.change(e)}
/>
<label>Email </label>
<input
type="text" id="Email"
name ="Email"
placeholder="Your Hotel ID.."
value = {this.state.fields.Email}
onChange ={e => this.change(e)}
/>
<label>Password</label>
<input
type="password"
id="password"
name ="password"
placeholder="Your User Password..."
value = {this.state.fields.password}
onChange ={e => this.change(e)}
/>
<label>Retrive property * </label><input type="submit" value="Submit" />
<p>{JSON.stringify(this.state.fields)}</p>
</form>
</div>
</center>
</div>
);
}
}
App.js:
import React, { Component } from 'react';
import './App.css';
//import './Temp.css';
import Insert from "./Insert.js";
import Design_bookingcom from "./Design_bookingcom.js";
class App extends Component {
render() {
return (
<div >
<Insert />
</div>
);
}
}
export default App;
Perl file
insert.js
#!/usr/bin/perl
use CGI qw(:all);
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Headers;
use HTTP::Response;
use Data::Dumper;
use Encode;
use LWP::Simple::Post("post_xml");
use XML::Simple;
use CGI;
use JSON;
use DBI;
my $cgi = new CGI;
my $json_response;
my $response;
# Header to fatch the data from react js file
print $cgi->header(
-type => 'text/json',
-access_control_allow_origin => '*',
-access_control_allow_headers => 'content-type',
-access_control_allow_methods => 'POST',
-access_control_allow_credentials => 'true',
);
# END
$response = $cgi->param('POSTDATA');
my $json = decode_json($response);
my $username = $json->{'Username'};
my $Email = $json->{'Email'};
my $Fullname = $json->{'Fullname'};
my $department = $json->{'department'};
my $password = $json->{'password'};
my $driverr="mysql";
my $db="krunal";
my $driver="DBI:$driverr:database=$db";
my $userid="root";
my $password="passwd";
my $conn =DBI->connect($driver,$userid,$password) or die $DBI::errstr;
$qry="INSERT INTO employee(emp_id,emp_username,emp_fullname,emp_dept,emp_psasword,emp_email) VALUES('',?,?,?,?,?)";
$statement=$conn->prepare("$qry");
$statement->execute($username,$Fullname,$department,$password,$Email);
$final = $statement->finish();
print $final;

Categories