我在reactJS应用程序中有一个表单。这是到目前为止的代码(很抱歉,很多)
import React from 'react';
import '../styles/app.css';
function validateDollar(value) {
var regex = /^[1-9]\d*(((,\d{3}){1})?(\.\d{0,2})?)$/;
if (regex.test(value))
{
//Input is valid, check the number of decimal places
var twoDecimalPlaces = /\.\d{2}$/g;
var oneDecimalPlace = /\.\d{1}$/g;
var noDecimalPlacesWithDecimal = /\.\d{0}$/g;
if(value.match(twoDecimalPlaces))
{
//all good, return as is
return value;
}
else
{
if(value.match(noDecimalPlacesWithDecimal))
{
//add two decimal places
return value + "00";
}
else
{
if(value.match(oneDecimalPlace ))
{
//ad one decimal place
return value + "0";
}
else
{
//else there is no decimal places and no decimal
return value + ".00";
}
}
}
}
else
{
return -1;
}
}
class Enterproperty extends React.Component {
constructor(props) {
super(props);
this.state = {
numberUnits: 0,
name: {
valid: true,
value: '',
label: 'Property Nickname',
length: 0,
css: 'input-group-text text-black input-size-200'
},
address: {
valid: true,
value: '',
label: 'Property Address',
length: 0,
css: 'input-group-text text-black input-size-200'
},
city: {
valid: true,
value: '',
label: 'Property City',
length: 0,
css: 'input-group-text text-black input-size-200'
},
price: {
valid: true,
value: '',
label: 'Asking price',
length: 0,
css: 'input-group-text text-black input-size-200'
},
taxes: {
valid: true,
value: '',
label: 'Taxes per year',
length: 0,
css: 'input-group-text text-black input-size-200'
},
expenses: {
valid: true,
value: '',
label: 'Net Operating Expenses',
length: 0,
css: 'input-group-text text-black input-size-200'
},
caprate: {
valid: true,
value: '',
label: 'Cap Rate',
length: 0,
css: 'input-group-text text-black input-size-200'
},
yearbuilt: {
valid: true,
value: '',
label: 'Building built in:',
length: 0,
css: 'input-group-text text-black input-size-200'
},
numberofunits: {
valid: true,
value: '',
label: 'Nuber of units:',
length: 0,
css: 'input-group-text text-black input-size-200'
}
}
this.saveData = this.saveData.bind(this);
this.yearBuilt = this.yearBuilt.bind(this);
this.setUnitNumber = this.setUnitNumber.bind(this);
}
setUnitNumber() {
let currentComponent = this;
var localUnitCount = document.getElementById("inputNumberOfUnits").value;
currentComponent.setState({ numberUnits:localUnitCount });
}
saveData() {
let currentComponent = this;
var validData = true;
var localName = {
valid: true,
value: '',
label: 'Property Nickname',
length: 0,
css: 'input-group-text text-black input-size-200'
}
var localAddress = {
valid: true,
value: '',
label: 'Property Address',
length: 0,
css: 'input-group-text text-black input-size-200'
}
var localCity = {
valid: true,
value: '',
label: 'Property City',
length: 0,
css: 'input-group-text text-black input-size-200'
}
var localPrice = {
valid: true,
value: '',
label: 'Asking price',
length: 0,
css: 'input-group-text text-black input-size-200'
}
var localExpenses = {
valid: true,
value: '',
label: 'Net Operating Expenses',
length: 0,
css: 'input-group-text text-black input-size-200'
}
var localCapRate = {
valid: true,
value: '',
label: 'Cap Rate',
length: 0,
css: 'input-group-text text-black input-size-200'
}
var localTaxes = {
valid: true,
value: '',
label: 'Taxes per year',
length: 0,
css: 'input-group-text text-black input-size-200'
}
// validate the property nickname
localName.value = document.getElementById("lblName").value;
localName.length = localName.value.length;
if (localName.length < 5) {
validData = false;
localName.valid = false;
//localName.label = "You did not enter a property nickname (minimum of 5 charaters)";
localName.css = "input-group-text text-danger input-size-200";
}
// validate the property address
localAddress.value = document.getElementById("lblAddress").value;
localAddress.length = localAddress.value.length;
if (localAddress.length < 3) {
validData = false;
localAddress.valid = false;
//localAddress.label = "You did not enter a property Address (minimum of 5 characters)";
localAddress.css = "input-group-text text-danger input-size-200";
}
// validate the property city
localCity.value = document.getElementById("lblCity").value;
localCity.length = localCity.value.length;
if (localCity.length < 3) {
validData = false;
localCity.valid = false;
//localCity.label = "You did not enter a property city (minimum of 3 characters)";
localCity.css = "input-group-text text-danger input-size-200";
}
// validate the property price
localPrice.value = validateDollar(document.getElementById("lblPrice").value);
if (localPrice.value < 0){
localPrice.value = "";
validData = false;
localPrice.valid = false;
//localPrice.label = "You entered an invalid dollar amount for the cost of the building";
localPrice.css = "input-group-text text-danger input-size-200";
}
// validate the property taxes
localTaxes.value = validateDollar(document.getElementById("lblTaxes").value);
if (localTaxes.value < 0){
localTaxes.value = "";
validData = false;
localTaxes.valid = false;
//localTaxes.label = "You entered an invalid dollar amount for the taxes on the building";
localTaxes.css = "input-group-text text-danger input-size-200";
}
// validate the Cap Rate
localCapRate.value = validateDollar(document.getElementById("lblCapRate").value);
if (localCapRate.value < 0){
localCapRate.value = "";
validData = false;
localCapRate.valid = false;
//localTaxes.label = "You entered an invalid dollar amount for the taxes on the building";
localCapRate.css = "input-group-text text-danger input-size-200";
}
// validate the net operating expenses
localExpenses.value = validateDollar(document.getElementById("lblExpenses").value);
if (localExpenses.value < 0){
localExpenses.value = "";
validData = false;
localExpenses.valid = false;
//localExpenses.label = "You entered an invalid dollar amount for the taxes on the building";
localExpenses.css = "input-group-text text-danger input-size-200";
}
currentComponent.setState({ name:localName, address:localAddress, city:localCity, price:localPrice, taxes:localTaxes, expenses:localExpenses, caprate:localCapRate });
}
yearBuilt() {
var date = new Date();
var startYear = date.getFullYear();
var endYear = startYear - 120;
let items = [];
for (let i = startYear;i>endYear;i--) {
items.push(<option key={i} value={i}>{i}</option>);
//here I will be creating my options dynamically based on
//what props are currently passed to the parent component
}
return items;
}
renderData = () => {
var localUnitCount = this.state.numberUnits;
var idArray = [];
for (var counter=0;counter<localUnitCount;counter++) {
var id = '';
var idObject = {
counter: 0,
idNameBedroom: '',
idNameBathroom: '',
idRent: '',
idMarket: '',
idRentedStatus: ''
}
//build the id for the bedroom item
if (counter<10) {id="Bedroom0"} else {id="Bedroom"};
id=id+counter;
idObject.idNameBedroom = id+(counter+1);
//build the id for the bathroom item
if (counter<10) {id="Bathroom0"} else {id="Bathroom"};
id=id+counter;
idObject.idNameBathroom = id+(counter+1);
//build the id for the rent item
if (counter<10) {id="Rent0"} else {id="Rent"};
id=id+counter;
idObject.idRent = id;
//build the id for the mareket item
if (counter<10) {id="Market0"} else {id="Market"};
id=id+counter;
idObject.idMarket = id;
//build the id for the rented status item
if (counter<10) {id="RentedStatus0"} else {id="RentedStatus"};
id=id+counter;
idObject.idRentedStatus = id;
idObject.counter = counter+1;
idArray[counter] = idObject;
}
return idArray.map( item => (
<div>
<hr />
<div className="text-black text-bold">
<label> Unit {item.counter} </label>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text text-black input-size-200">Rent for Unit {item.counter}</span>
</div>
<input id={item.idRent} type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text text-black input-size-200">Rented status of Unit {item.counter}</span>
</div>
<select className="custom-select text-black" id={item.idRentedStatus}>
<option value="rented" selected>Rented</option>
<option value="vacant">Vacant</option>
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text text-black input-size-200">Bedrooms in Unit {item.counter}</span>
</div>
<select className="custom-select text-black" id={item.idNameBedroom}>
<option value="1" selected>1 bedroom</option>
<option value="2">2 bedrooms</option>
<option value="3">3 bedrooms</option>
<option value="4">4 bedrooms</option>
<option value="5">5 bedrooms</option>
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text text-black input-size-200">Bathrooms in Unit {item.counter}</span>
</div>
<select className="custom-select text-black" id={item.idNameBathroom}>
<option value="1" selected>1 bathroom</option>
<option value="2">2 bathrooms</option>
<option value="3">3 bathrooms</option>
<option value="4">4 bathrooms</option>
<option value="5">5 bathrooms</option>
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text text-black input-size-200">Rent category for Unit {item.counter}</span>
</div>
<select className="custom-select text-black" id={item.idMarket}>
<option value="market" selected>Market value</option>
<option value="stabalized">Rent stabalized</option>
<option value="controlled">Rent controlled</option>
</select>
</div>
</div>
) )
}
render() {
console.log(this.state.caprate.value);
return (
<div className="App">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="#">Property Management</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav mr-auto">
<li className="nav-item">
<a className="nav-link" href="/loadProperty">View Saved Properties</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/Enterproperty">Enter New Property</a>
</li>
</ul>
</div>
</nav>
<div className="d-flex flex-wrap justify-content-center position-absolute w-100 align-items-center align-content-center">
<div className="container">
<div className="row">
<div md="6">
<form>
<p className="h4 text-center py-4">Enter the property information</p>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.name.css}>{this.state.name.label}</span>
</div>
<input id="lblName" type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.address.css}>{this.state.address.label}</span>
</div>
<input id="lblAddress" type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.city.css}>{this.state.city.label}</span>
</div>
<input id="lblCity" type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.price.css}>{this.state.price.label}</span>
</div>
<input id="lblPrice" type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.taxes.css}>{this.state.taxes.label}</span>
</div>
<input id="lblTaxes" type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.expenses.css}>{this.state.expenses.label}</span>
</div>
<input id="lblExpenses" type="text" className="form-control" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.caprate.css}>{this.state.caprate.label}</span>
</div>
<input id="lblCapRate" type="text" className="form-control" value={this.state.caprate.value}/>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.yearbuilt.css}>Tax abatements?</span>
</div>
<select className="custom-select text-black" id="inputTaxAbatement">
<option value="yes" selected>Yes</option>
<option value="no">No</option>
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.yearbuilt.css}>Fuel Type</span>
</div>
<select className="custom-select text-black" id="inputFuelType">
<option value="gas" selected>Gas</option>
<option value="oil">Oil</option>
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.yearbuilt.css}>Tennants pay utilities</span>
</div>
<select className="custom-select text-black" id="inputTennantsPayUtilities">
<option value="yes" selected>Yes</option>
<option value="no">No</option>
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.yearbuilt.css}>{this.state.yearbuilt.label}</span>
</div>
<select className="custom-select text-black" id="inputYearBuilt">
{this.yearBuilt()}
</select>
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className={this.state.numberofunits.css}>{this.state.numberofunits.label}</span>
</div>
<select className="custom-select text-black" id="inputNumberOfUnits" onChange={() => {
this.setUnitNumber();
}}>
<option value="0" selected>Select</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
<option value="5">Five</option>
<option value="6">Six</option>
<option value="7">Seven</option>
<option value="8">Eight</option>
<option value="9">Nine</option>
<option value="10">Ten</option>
<option value="11">Eleven</option>
<option value="12">Twelve</option>
<option value="13">Thirteen</option>
<option value="14">Fourteen</option>
<option value="15">Fifteen</option>
<option value="16">Sixteen</option>
<option value="17">Seventeen</option>
<option value="18">Eighteen</option>
<option value="19">Nineteen</option>
<option value="20">Twenty</option>
</select>
</div>
<div>
{this.renderData()}
</div>
<div className="text-center py-4 mt-3">
<button type="button" className="btn btn-primary" onClick={() => {
this.saveData();
}}>Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default Enterproperty;
saveData()中的代码验证输入字段的值。
我专门查看需要确保将其输入为美元金额的数字字段。
验证字段之后,我执行setState以使用新值更新状态。状态更新后,react将重新呈现并显示表单。
我的问题是,如果我在上限率的表单字段中输入12345并单击按钮,则console.log()显示我将值12345验证为“ 12345.00”。我在return()之前的渲染器中有一个console.log(),this.state.caprate.value的值是12345.00,但是当渲染发生时,表单仍然显示旧值。
验证字段并在验证完成后使字段可编辑的正确方法是什么?