I have a form with two inputs, which acts as a calculator of sorts. Think of something like a mortgage calculator. A user needs to be able to input a value into input a (int or decimal), and have it calculate some value for input b. Likewise, a user must be able to input a value into input b (int), and have it calculate a value for input a. The values should calculate as the user types.
I have the calculation working, but I'm running into problems when I try to either a: empty the field to start over; or b: attempt to input a decimal into input a.
In the first case, neither input will let me remove the final character. Even if I highlight the entire value and hit backspace, the input stays at whatever value was there.
In the second case, the decimal never takes. If I try to type in 2.2, I get 22 instead.
Per the React documentation, I'm using an onChange event handler, which sets the state of my component, and then the inputs display that state.
Code example is here:
handleIntervalChange: ->
iVal = parseFloat #refs.confidenceInterval.getDOMNode().value
iVal = iVal/100
lVal = parseFloat #refs.confidenceLevel.getDOMNode().value
return false if _.isNaN ival
docCount = #calcDocsByCLevel lVal, iVal
docCount = null if _.isNaN(docCount) or docCount is Infinity
#setState
targetCLevel: lVal
targetCInterval: iVal
docCount: docCount
handleDocChange: ->
docCount = parseInt #refs.docCount.getDOMNode().value
return false if _.isNaN docCount
lVal = parseFloat #refs.confidenceLevel.getDOMNode().value
#setState
targetCLevel: lVal
targetCInterval: #calcIntervalByDocCount lVal, docCount
docCount: docCount
render: ->
<fieldset>
<div className='controls'>
<label htmlFor='confidence-interval'>
Confidence interval (%)
</label>
{<ValidatorTooltip errors={#state.errors['confidence-interval']}/> if #state.errors}
<input type='text' id='confidence-interval'
className={cIntervalClasses} ref='confidenceInterval'
value={#state.targetCInterval * 100}
onKeyUp={#handleKeyUp} onChange={#handleIntervalChange} />
</div>
<div className='controls'>
<label htmlFor='doc-count'>Number of documents</label>
{<ValidatorTooltip errors={#state.errors['doc-count']}/> if #state.errors}
<input type='text' id='doc-count' className={docClasses}
ref='docCount' onChange={#handleDocChange} onKeyUp={#handleKeyUp}
value={#state.docCount} />
</div>
</fieldset>
Got it. The problem was in my calculation methods - I needed some logic to catch if the document or interval fields were blank (and would then render the other fields blank).
Related
Using react-hook-form, and zod within a Next.js project. Trying to get .optional() to work. It works with simple strings. See the schema below.
//works
const FormSchema = z.object({
website: z.string().optional()
});
But it does not work when I add the .url() flag. It only checks for the valid url. If the field is blank, it throws an error. In other words, the field is no longer optional. It accepts a valid url, but not a blank input field. Of course I want it to accept a blank input and a valid url as the only valid inputs.
//not working. the field is no longer optional.
const FormSchema = z.object({
website: z.string().url().optional()
})
Perhaps the problem has to do with the input field returning the wrong data-type when it's blank?
<label className="block">
<span className="block text-white">Website</span>
<input
id="email-input"
type="text"
className={`block border text-lg px-4 py-3 mt-2 border-gray-200 focus:bg-white text-gray-900 focus:ring-purpleLight focus:ring-2 outline-none w-full disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed`}
{...register("website")}
disabled={isSubmitting}
placeholder="Website"
value={undefined}
/>
</label>
{errors.website && (
<p className="mt-1 text-sm text-red-600">
{errors.website.message}
</p>
)}
Perhaps the problem has to do with the input field returning the wrong data-type when it's blank?
I think this is likely your problem, although I'm not familiar with what react-hook-form might be doing to transform the input before handing it to your schema. The empty field will have the empty string '' as a value when it's blank. If you just use zod directly:
z.string().optional().parse(''); // succeeds because '' is a string
// Whereas this will fail because although '' is a string, it does not
// match the url pattern.
z.string().url().optional().parse('');
.optional() allows for the input value to be undefined so for example:
// These will both successfully parse because of `optional`
z.string().optional().parse(undefined);
z.string().url().optional().parse(undefined);
Going out slightly on a limb here, but if you wanted '' to pass you could add a preprocess step where you convert '' to undefined:
const s = z.preprocess(
(arg) => (arg === "" ? undefined : arg),
z.string().url().optional()
);
console.log(s.safeParse("")); // success (data: undefined)
console.log(s.safeParse("test")); // failure (not a url)
console.log(s.safeParse(undefined)); // success (data: undefined)
I am trying to search for the right method to submit HTML form with the data from excel cell and retrieve part of the result back.
HTML form URL is http://www2.stat.gov.lt:8777/imones/sektor.html:
<form action="sektor.chk_sekt" method="POST">
<br>
<b>Ūkio subjekto kodas: </b>
<input type="text" name="imone01" size="9" maxlength="9">
<br>
<br>
<input type="submit" value=" OK ">
</form>
Example data strings to submit are 303305024, 300983557, the value to be extracted from the response on the page http://www2.stat.gov.lt:8777/imones/sektor.chk_sekt is the line:
<BR>
<B>Veiklos rūšis pagal EVRK red. 2: </B>
479100 - Užsakomasis pardavimas paštu arba internetu
<BR>
The values from each cell in column A should be submitted within loop, and the retrieved results should be filled into corresponding cells in column B.
I have reviewed several similar questions but they seem to be using some different format of form and doesn't suit in this case.
Here is the example using XHR and RegEx to retrieve the data you need:
Option Explicit
Sub RetriveData()
Dim i As Long
For i = 1 To Cells.Rows.Count
If Cells(i, 1).Value = "" Then Exit For
Cells(i, 2).Value = GetData(Cells(i, 1).Value)
Next
End Sub
Function GetData(sCompany As String) As String
Dim sContent As String
With CreateObject("MSXML2.XMLHTTP")
.Open "POST", "http://www2.stat.gov.lt:8777/imones/sektor.chk_sekt", False
.Send "imone01=" & sCompany
sContent = .ResponseText
End With
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = "<head>[\s\S]*?</head>|(?!<br>)<[^>]*>|[\r\n\t]*"
sContent = .Replace(sContent, "")
.Pattern = "<BR>Veiklos r\u016B\u0161is pagal EVRK red. 2: (.*?)<BR>"
With .Execute(sContent)
If .Count = 1 Then GetData = .Item(0).SubMatches(0) Else GetData = "n/a"
End With
End With
End Function
The output is as follows for me:
HTML
<ion-input [(ngModel)]="login.username" ngControl="username1" type="number" #username1="ngForm" id="userName" required>
</ion-input>
PROTRACTOR TEST CODE
let usern: ElementFinder = element.all(by.css('.text-input')).get(0);
usern.sendKeys('error');
expect(usern.getAttribute("value")).toEqual("error");
browser.sleep(500);
usern.clear();
browser.sleep(1000);
usern.sendKeys('12345');
The element is found but no text is entered into the field. If I change the element to type="text" the protractor command works.And the page view is 'e' and can't be clear.
Secondly if I send string like this: "we2124will", the actually send data is '2124' and the result from getAttribute("value") is 2124.
Thirdly even if I changed the sendKeys to number, the result is not full number string. For example:
Failures:
1) Login page should input username and password
Message:
Expected '125' to equal '12345'.
Stack:
Error: Failed expectation
There are some number missing.
Since you're using an <ion-input>, the actual HTML <input> tag will be nested within, and it won't have an id attribute. The effect is that the wrong element can get selected.
Try something like below to grab the nested input tag:
let username = element(by.id('userName')).all(by.tagName('input')).first();
username.sendKeys('fakeUser');
That worked for me.
As a workaround, you can introduce a reusable function that would perform a slow type by adding delays between send every key.
First of all, add a custom sleep() browser action, put this to onPrepare():
protractor.ActionSequence.prototype.sleep = function (delay) {
var driver = this.driver_;
this.schedule_("sleep", function () { driver.sleep(delay); });
return this;
};
Then, create a reusable function:
function slowSendKeys(elm, text) {
var actions = browser.actions();
for (var i = 0, len = text.length; i < len; i++) {
actions = actions.sendKeys(str[i]).sleep(300);
}
return actions.perform();
}
Usage:
var elm = $("ion-input#userName");
slowSendKeys(elm, "12345");
What version of protractor are you using?
Not sure this is the issue but try grabbing the element by ng-model
var elem = element(by.model('login.username'));
elem.sendKeys('error');
expect(elem.getAttribute("value")).toEqual("error");
elem.clear();
elem.sendKeys('12345');
expect(elem.getAttribute("value")).toEqual("12345");
I'm trying to set up a simple select dropdown form with Flask. Based on the option chosen, I grab different data from my database, and display it back into a div on my html template. But I can't seem to get the Flask request to register any of the select options. When I print request.form or request.args, I always get empty Dicts. It's probably something simple I'm missing but I can't seem to find the problem. I've gotten this to work with several input and button forms, but I can't get it to work right for selects.
Here is a bit of my html template code, with the form and select. I've tried both GET and POST method in the form.
<div class="options" id="options">
<form class="form-horizontal container-fluid" role="form" method="GET" action="exploresn2.html">
<div class="form-group">
<label for="xaxis" class="col-sm-2 control-label">X-axis:</label>
<div class="col-sm-2">
<select name="xaxis" class="form-control" id="xaxis">
<option selected value="mjd" id="mjd">MJD</option>
<option value="seeing" id="seeing">Seeing</option>
<option value="airmass" id="airmass">Airmass</option>
<option value="hourangle" id="hourangle">Hour Angle</option>
</select>
</div>
</div>
</form>
</div>
In Flask, at first, I tried inside my app
import flask
from flask import request, render_template, send_from_directory, current_app
explore_page = flask.Blueprint("explore_page", __name__)
#explore_page.route('/exploresn2.html', methods=['GET','POST'])
def explore():
xaxis = str(request.args.get("xaxis", "any"))
.... [populate new xaxis variable based on request option selected]
exploreDict['xaxis'] = xaxis
return render_template("exploresn2.html", **exploreDict)
or
mjd = valueFromRequest(key='mjd', request=request, default=None)
if mjd:
mjds = [int(exp.platedbExposure.start_time/(24*3600)) for exp in exposures]
xaxis = mjds
exploreDict['xaxis'] = xaxis
to look for and grab a specific values, or in the first case, any value select. The valueFromRequest is function that grabs data from either GET or POST requests.
but this returns nothing, and then I tried just printing the entire request.args (or request.form) and it returns and empty Dict. Everything I try it still returns empty Dicts. So I'm missing some set up somewhere I think but the form looks right to me?
I'm not sure if this is the actual answer to this problem that I was looking for, but here is what I came up with. I couldn't actually get the Flask to accept a GET request into the original explore method defined, so I implemented a new method in Flask to return a JSON object
#explore_page.route('/getdata', methods=['GET','POST'])
def getData(name=None):
name = str(request.args.get("xaxis", "mjd"))
xaxis = 'populate new xaxis data based on value of name'
data = '(x,y) data array filled with values for plotting'
axisrange = range of x,y data for axes for plot
return jsonify(result=data, range=axisrange)
and then I just made a GET request via javascript to that method whenever the select button changes. So in my exploresn2.html template I have (using Flot for plotting)
$("#xaxis").change(function(){
var newname = $("#xaxis :selected").text();
var axes = plot.getAxes();
options = plot.getOptions();
var plotdata = plot.getData();
// make a GET request and return new data
$.getJSON($SCRIPT_ROOT + '/getdata', {'xaxis':$("#xaxis :selected").val()},
function(newdata){
// set new data
for (var i = 0; i < plotdata.length; ++i) {
plotdata[i].data = newdata.result[plotdata[i].label];
}
// set new axes
axes.xaxis.options.panRange = [newdata.range[0]-50,newdata.range[1]+50];
axes.xaxis.options.axisLabel = newname;
axes.xaxis.options.min = newdata.range[0]-1;
axes.xaxis.options.max = newdata.range[1]+1;
axes.yaxis.options.min = newdata.range[2];
axes.yaxis.options.max = newdata.range[3];
// redraw plot
plot.setData(plotdata);
plot.setupGrid();
plot.draw();
});
});
In jQuery, there is a function to serialize a form element so for example I can submit it as an ajax request.
Let's say we have a form such as this:
<form id="form">
<select name="single">
<option>Single</option>
<option selected="selected">Single2</option>
</select>
<input type="checkbox" name="check" value="check1" id="ch1">
<input name="otherName" value="textValue" type="text">
</form>
If I do this with the help of jquery
var str = $( "form" ).serialize();
console.log(str);
the result would be
single=Single2&check=check1&otherName=textValue
Is there such functionality in dart's FormElement or I have to code it myself? Thanks.
I came up with my own simple solution that might not work in all cases (but for me it is workikng). The procedure is this:
First we need to extract all input or select element names and values from the form into Dart's Map, so the element name will be the key and value the value (e.g. {'single': 'Single2'}).
Then we will loop through this Map and manually create the resulting string.
The code might look something like this:
FormElement form = querySelector('#my-form'); // To select the form
Map data = {};
// Form elements to extract {name: value} from
final formElementSelectors = "select, input";
form.querySelectorAll(formElementSelectors).forEach((SelectElement el) {
data[el.name] = el.value;
});
var parameters = "";
for (var key in data.keys) {
if (parameters.isNotEmpty) {
parameters += "&";
}
parameters += '$key=${data[key]}';
}
Parameters should now contain all the {name: value} pairs from the specified form.
I haven't seen anything like that yet.
In this example Seth Ladd uses Polymers template to assign the form field values to a class which get's serialized.