How to compare value of HTML input in-line - html

I'd like an input which has a 'highlight' class if value != defaultValue.
Due to the library I am using, I can't reliably use names or onChange events. (If needed, I can do it, but it'll be a pain to set up).
Currently it looks like:
<td><input type="number" className={(this.value !== this.defaultValue ? 'highlight' : '')} defaultValue={1}/></td>
I get an error when trying to use 'this.value' or 'this.defaultValue' because the context for 'this' refers to the page, not the element.
Is there an in-line way I can get this value for comparison?

As best as I could find, there's no way to do this.
The solution I came up with was,
<td><input id={table.ID.toString()} type="number" onChange={() => highlightElement(table.ID.toString()} defaultValue={table.defaultValue}/> </td>
And defined highlightElement() as:
function highlightElement(id:string){
const element = document.getElementById(id);
element.style.backgroundColor = "#FDFF47";
}
...There's probably a way I could also input the intended default value as a function parameter and get the current value of the input, compare the two, and if matched DON'T highlight it, else apply the style. But this suits what I currently need.

Related

Is there a easy way to handle input type="number" as a default negative value?

I've tried filling the value on init with a "-" sign but only got the Error-Message:
The specified value "-" cannot be parsed, or is out of range.
Another attempt was to just accept every value as negative if it doesn't start with a "+" sign but when reading the value property the sign wasn't included.
Does anyone know an easy way to handle an input type="number" as a negative and only make it positive when explicitly stated?
Preferably in a user-friendly way. I don't want a check-box to handle that.
Specifics:
i have an input Field in html
<input type="number" #testAmount>
I want to handle the value as negative when not explicitly stated otherwise.
so my first attempt was this in TS:
#ViewChild('testAmount') testAmount: ElementRef<HTMLInputElement> | undefined = undefined;
ngOnInit() {
if(!!this.testAmount){
console.log('set amount value');
console.log(this.testAmount.nativeElement.value);
this.testAmount.nativeElement.value = '-'
}
}
that's when i got the error message above:
The specified value "-" cannot be parsed, or is out of range.
Attempt 2:
In my second attempt figured to just accept any value and treat it as negative and only once the user puts a "+" before the value it would be a positive.
but that didn't work out, because when i read the value like this:
console.log(this.testAmount.nativeElement.value)
i was given the value without the + sign, presumably because it was interpreted as a number and thus the + sign was automatically removed.
To Be clear
All i want is that the user doesn't have to add the minus sign every time he adds a value, because negative values will be the norm.
But a positive value shall still be possible it is just rather rare.
Solution?
Best solution i've found so far is to give my input a KeyDown event and handle the very first key-input, it's not perfect but i think it'll get the job done most of the time:
inputHasBeenMade = false
onKeyDown(event: KeyboardEvent) {
if(!this.inputHasBeenMade && !!this.amount){
if(event.key !== "+"){
event.preventDefault()
this.amount.nativeElement.value = '-' + event.key
}
this.inputHasBeenMade = true
}
}
i don't think it's a good solution so i won't write it down as an answer (for now) in the hopes that someone will come up with a better solution.
type number can't have a "-" string.
you can specify -78 or some other number without the ""
Change
let myValue = '-';
this.testAmount.nativeElement.value = myValue
To
let myValue = -5;
this.testAmount.nativeElement.value = myValue;
You are creating a minus symbol when you wrap it with a single ' or a " double quote, and this makes it a string. Remove the quotes and it will be an integer.
You can also look at casting a string to an int if that's required, but not good practice.

Tally Up Number of Occurrences in Angular

So basically I have this quiz app im working on using angular and I want to tally up the amount of times the right answer is entered. I already made it so the words 'CORRECT' are displayed by the question if they type the right answer in the text box, but I want to see how many times that happens. Here is my code
div ng-repeat="q in questions">
<span>{{ q.question }}</span><br>
<input type="text" ng-model="q.ans" name="email" placeholder="">
<div ng-show="q.ans===q.answer">CORRECT!</div>
<div>
so basically questions is just an array with a question string and answer string. I want to see at the end how many are correct. So I'm thinking, I added in a correct property to the question objects that has a default of 0 which could mean wrong, and change when its right to 1.
Now how would I make it change from the html page here when someone types the right answer? like if correct is shown, if the ng-show is right, then that value would be 1, if not, it'd be 0.
thanks for any assistance. Wondering if I could do this in real time instead of having a 'check' button at the end.
EDIT: okay I looking around the ng-if directive, would it somehow be possible to add like
<div ng-if="q.ans===q.answer">{{ q.correct = 1 }} </div>
or somehow execute that q.correct = 1 (meaning that answer is correct) if the ng-if block is run?
Make a filter for counting the correct answers
// app is your module
app.filter('correctCount', function() {
return function(questions) {
return questions.reduce(function(count, q) {
return count + (q.ans === q.answer ? 1 : 0);
}, 0);
};
})
Then you can display the total in your template
Total: {{questions | correctCount | number}}
Demo ~ http://plnkr.co/edit/br3fxHQ8q04ajZj6Fxch?p=preview
An alternative to reduce that might be easier to understand is...
return questions.filter(function(q) {
return q.ans === q.answer;
}).length;

How to create an input field (HTML) that spans two lines

I want to be able to use an <input> field type of control but allow only two lines.
At the moment I am using two fields but was wondering if anyone can come up with a solution to allow input (similar to a textarea) but no more than two lines. I control the width etc of the field.
For reference, Jquery and Bootstrap 3 are loaded.
Any help much appreciated.
try this
var element = document.getElementById('tworows');
make2Lines(element);
function make2Lines(el){
el.setAttribute('rows', 2); // limit height to 2 rows
// el.setAttribute('wrap', 'off'); // ensure no softwrap is not required anymore if we limit the length
el.addEventListener('keydown', limit); // add listener everytime a key is pressed
function limit(e){
if(e.keyCode == 13 && this.value.indexOf('\n')>-1){
// 13 is the ENTER key and \n is the value it make in the textarea
// so if we already have a line break and it's the ENTER key, we prevent it
e.preventDefault();
}
// async to let the dom update before changin the value
setTimeout(limitRow.bind(this), 0);
}
function limitRow(){
var maxLength = 10;
var rows = this.value.split('\n');
rows.forEach(cutOverflow)
this.value = rows.join('\n');
function cutOverflow(row, index, rows) {
rows[index] = row.substring(0, maxLength);
// this if is only if you want to automatically jump to the next line
if (index === 0 && row.length > maxLength)
rows[1] = row.substring(maxLength) + (rows[1] || '');
}
}
}
<textarea id="tworows"></textarea>
short version : function make2Lines(a){function b(a){13==a.keyCode&&this.value.indexOf("\n")>-1&&a.preventDefault(),setTimeout(c.bind(this),0)}function c(){function c(b,c,d){d[c]=b.substring(0,a),0===c&&b.length>a&&(d[1]=b.substring(a)+(d[1]||""))}var a=10,b=this.value.split("\n");b.forEach(c),this.value=b.join("\n")}a.setAttribute("rows",2),a.addEventListener("keydown",b)}
Two ways come to mind:
You could use a <textarea> instead, and augment it with some script that only allows two lines.
You could continue to use two <input> fields, but style them so they stack on top of each other to create the illusion of one field. You might still need a bit of script to take care of some usability annoyances, such as pressing ENTER to go from line one to line two.
If you are talking about wrapping lines if the text is too long, according to documentation <input type="text"> cannot wrap text.
However, if you are talking about limiting the character length, you could use the maxlength attribute like- <input type="text" maxlength="10">
An input field can only display one line http://www.w3.org/TR/html-markup/input.text.html#input.text. For multiline you need to use textarea and set the rows attribute. If you need two separate values you can do it after in PHP, Javascript or other means.
<textarea class="form-control" rows="2">The default text or empty for nothing this is passed as value for this field</textarea>

Handling checkboxes and getting values

I'm pretty new to MVC and I'm having a hard understanding how to get the values (basically the IDs) to checkboxes that I'm generating. Here are my checkboxes:
<div id='myCheckboxDiv'>
<input type="checkbox" onclick="checkAll(this)">Check All
#foreach (var form in #Model.DetailObject.DoaFormGroupDocuments)
{
<br>
var checkBoxId = "chk" + form.DocumentId;
#Html.CheckBox(checkBoxId, new { value = form.DocumentId, #checked = true });
#form.DocumentName;
}
</div>
Essentially what I want to do is get the ID to which ever checkbox is checked and save it in to a list after I click a save button at the bottom of the page.
I have run across something like this to handle everything but I'm not quite sure how to use it really...
var values = $('#myCheckboxDiv').find('input:checkbox:checked').map(function () {
// get the name ..
var nameOfSelectedItem = this.attr('name');
// skip the ‘chk’ part and give me the rest
return nameOfSelectedItem.substr(3);
}).get();
The only thing you need to think about is the value of the name attribute your checkbox(es) will have. The way you're handling it right now, your post body is going to have a fairly randomized collection of chkN-named parameters, where N is some number. The modelbinder will need something similarly named as a parameter to your action method in order to bind the posted values to something useful. That's a tall order for something that will be some what variable (the DocumentId values).
The best option would be to set up your checkboxes, instead, as a collection, which means giving them names chk[0], chk[1], etc. Then in your action you can accept a parameter like List<string> chk, and that will contain a list of all the values that were posted.

How to get value of a hidden element? (Watir)

just wondering, how can I get the value of a hidden element using watir? This is the element:
<input type="hidden" value="randomstringhere" id="elementid" name="elementname" />
And this is my code atm:
require "rubygems"
require "watir-webdriver"
$browser = Watir::Browser.new :ff
$browser.goto("http://www.site.com")
$grabelement = $browser.hiddens(:id, "elementid")
$blah = $grabelement.attribute_value("value")
puts $blah
This gets stuck at the last line, where it returns
code.rb:6:in `<main>': undefined method `attribute_value' for #<Watir::HiddenCollection:0x8818adc> (NoMethodError)
Sorry for the basic question, I've had a search and couldn't find anything.
Thanks in advance!
Problem
Your code is quite close. The problem is the line:
$grabelement = $browser.hiddens(:id, "elementid")
This line says to get a collection (ie all) of hidden elements that have id "elementid". As the error message says, the collection does not have the attribute_value method. Only elements (ie the objects in the collection) have the method.
Solution (assuming single hidden with matching id)
Assuming that there is only one, you should just get the first match using the hidden instead of hiddens (ie drop the s):
$grabelement = $browser.hidden(:id, "elementid")
$blah = $grabelement.value
puts $blah
#=> "randomstringhere"
Note that for the value attribute, you can just do .value instead of .attribute_value('value').
Solution (if there are multiple hiddens with matching id)
If there actually are multiple, then you can iterate over the collection or just get the first, etc:
#Iterate over each hidden that matches
browser.hiddens(:id, "elementid").each{ |hidden| puts hidden.value }
#Get just the first hidden in the collection
browser.hiddens(:id, "elementid").first.value