unable to delete character from input - javascript

I am debugging a project built by someone else and there's this strange issue where one of the form boxes cannot delete the last character.
The code uses two JS files, one mostly with React and the other with jQuery (I heard it was a legacy project that got outsourced and someone else just put react on top of it).
Now, because the code is 8000 lines long, it's been relatively difficult for me to debug (especially when they name everything the same...).
I was wondering if anyone would have any pointers? I checked the state and I can see that the value of the form input is changing (if the word "hello" is there and I delete all the way to "h" and delete again, "h" still stays in the box, but "h" is gone from the "value" field and from the state).
I suspected that it was a jQuery issue, but I do not see anything modifying the form input field values.
Another thing I've noticed is that I cannot CTRL + Delete or Highlight all and Delete at all (it works for the other boxes).
Here's a snippet of the React code for the input.
render: function() {
if( this.state.theData.length ) {
return (
<div id="to-airport-wrapper" className="wrapper">
<label htmlFor="to-airport" className="clear-inline-block">
{LEXICON.to}
<span className="sr-only">{LEXICON.cityOrAirport}</span>
<span id="wcag-to-airport" className="sr-only">{LEXICON.wcagFromToAirportLabel}</span>
<ToAirportLabel hasError={this.state.error}/>
</label>
<div id={"TO_LAW_"+this.props.groupIndex} className="list-airport-wrapper">
<input type="text" id="to-airport" className="from-to-airport full-width" name="to-airport"
onFocus={this.onFocus} onChange={this.change} placeholder={LEXICON.cityOrAirport}
aria-required="true" aria-autocomplete="list" autoComplete="off"
data-airportcode={this.state.airportcode} value={this.state.value}/>
<ul data-type="to-airport" className="list-airport list-unstyled">
{
this.state.data.map(function(item, i) {
return <li key={i} className="list-airport-item" data-shortname={item.shortName} data-airportcode={item.airportCode} tabIndex="-1"><span>{item.name}</span></li>
})
}
</ul>
</div>
</div>
);
} else {
return (
<div id="to-airport-wrapper" className="wrapper">
<label htmlFor="to-airport" className="clear-inline-block">{LEXICON.to}</label>
<div className="list-airport-wrapper">
<input type="text" id="to-airport" className="from-to-airport full-width" name="to-airport" onChange={this.change} disabled="true" aria-autocomplete="list" data-airportcode="" placeholder={LEXICON.cityOrAirport} autoComplete="off" value="" />
</div>
</div>
);
}
}
Here's the Change function:
change: function(event) {
GLOBAL.ToAirportSetAirportCode('', '');
console.log("TO VALUE!", event.target.value)
if( event.target.value ) {
var jsObjects = this.state.theData;
var result = jsObjects.filter(function( obj ) {
var airportName = obj.name.replace('(','\\(').replace(')','\\)');
var eventTargetValue = event.target.value.replace('(','\\(').replace(')','\\)');
return airportName.toLowerCase().search( eventTargetValue.toLowerCase() ) !== -1;
});
if( result.length > 0 ) {
$("#TO_LAW_"+this.props.groupIndex+ " ul").show();
this.setState({
data: result,
value:event.target.value
});
} else {
this.setState({
value:event.target.value
});
$("#to-airport + ul").hide();
}
} else {
this.setState({
data: this.state.theData,
value: event.target.value
});
}
if( event.target.value == "" || result.length == 0 ) {
this.reset(event.target.value);
}
}
The console.log for the TO VALUE disappears prematurely when I try to delete the last character in the form input.

Related

array removes the last element instead of the removed one react useState

I am trying to get this
https://www.youtube.com/watch?v=QyoSW2cP-RE
My code is here
https://codesandbox.io/s/ecstatic-shannon-gz3c2?fontsize=14&hidenavigation=1&theme=dark
I am trying to delete element when the input field is empty, and it is working in the array (the 2 buttons in the bottom are for logging the array and it's working fine) but in the ordered list something is going wrong, it is deleting the last element and letting the removed one empty not deleting it, what's the problem I don't understand ://
<ol>
{prosArr.map((e, key) => {
if (e !== '') {
console.log(e);
return (
<li key={key}>
<input
type="text"
onBlur={(el) => {
if (el.target.value === '') {
prosArr[prosArr.indexOf(e)] = '';
setProsArr(prosArr.filter((e) => e !== ''));
}
}}
defaultValue={e}
/>
</li>
);
} else {
return '';
}
})}
<li>
<input
onBlur={(e) => {
e.target.value !== '' && setProsArr([...prosArr, e.target.value]);
e.target.value = '';
}}
type="text"
/>
</li>
</ol>;
EDIT: I edited and copied the functionality code here, but there is the full working code on the sandbox link

Tranferring focus and clearing fields based on a barcode reading (VueJS)

I'm writing an app that runs on keyboard input but primarily as a barcode driven app. I'm having a hard time clearing some fields to reset the form after each button submission as well as refocusing on the correct field (the empty one)
Here's what it looks like
The Shipper ID doesn't clear unless I click that Black button or scan the barcode with value *CloseShipper*. It also loads empty the first time the page loads.
The Tracking # field clears and receives focus when I click the "Add To Batch" button or scan the barcode with value *AddToBatch*.
The App Barcode field clears immediately after I scan an App and adds it to an array that shows below it and receives focus right way to continue scanning non-stop until I finish the process by clicking or scanning the Add To Batch. (This part is working)
My problem is when I scan the *AddToBatch* barcode, nothing is happening. If I click it, the click event is being registered and it is clearing the fields that need to be cleared but the focus is still on the appbarcode. So, that's two problems separately.
Sorry I can't reproduce a working fiddle. Too many dependencies for it to work. So I'll post the relevant code here.
Template:
<form class="uk-form-horizontal uk-margin-medium barcodefields">
<div v-if="reset">
<div class="uk-margin">
<label
class="uk-form-label"
:for="_uid+'ctsinput'">
Shipper ID
</label>
<div class="uk-form-controls">
<input
class="uk-input"
:id="_uid+'ctsinput'"
name="shippernumber"
type="text"
maxlength="24"
:autofocus="'autofocus'"
v-focus
v-model.trim="shipperbarcode"
#input="runException"
/>
</div>
</div>
<div class="uk-margin">
<label
class="uk-form-label"
:for="_uid+'ctsinput'">
Tracking #
</label>
<div class="uk-form-controls">
<input
class="uk-input"
:id="trackingNumber"
name="trackingnumber"
type="text"
maxlength="24"
v-model.trim="trackingbarcode"
#input="runException"
/>
</div>
</div>
<div class="uk-margin">
<label
class="uk-form-label"
:for="_uid+'ctsinput'">
App. Barcode #
</label>
<div class="uk-form-controls">
<input
class="uk-input"
:id="_uid+'ctsinput'"
name="appbarcode"
type="text"
maxlength="24"
v-model.trim="applicationbarcode"
#change="addApplication"
/>
</div>
</div>
<!-- This is the list of apps scanned -->
<h5
v-if="this.appList.length !== 0"
class="heading-app-scanned"
>Applications Scanned In This Batch</h5>
<div
v-if="this.appList.length !== 0"
class="uk-card uk-card-secondary app-collection"
>
<div
v-for="appItem in appList"
:key="appItem.id"
class="app-scanned-item">
<div class="uk-padding-small">
<label class="uk-form-label">Application #:</label>
<span class="uk-text">{{appItem}}</span>
</div>
<div class="uk-divider"></div>
</div>
</div>
</div>
</form>
In my scripts, besides all props and data, etc, here is the logic part:
methods: {
...mapActions(["fetchBatches"]),
// evaluating the value of the shipperbarcode and trackingbarcode
runException: function(e) {
this.shipperbarcode = this.shipperbarcode.replace(/[^0-9.]/g, "");
this.trackingbarcode = this.trackingbarcode.replace(/[^0-9.]/g, "");
},
// evaluating what happens when an app is scanned
addApplication: function(e) {
let appBar = this.applicationbarcode;
if (
this.applicationbarcode === "*AddToBatch*" ||
this.applicationbarcode === "*CloseShipper*"
) {
this.applicationbarcode = "";
return;
} else {
this.counter += 1;
}
//give access to the add to batch function to trigger the modal window and close batch
this.addToBatch();
// send the qualifying barcodes to an array and clear the field for the next scan
this.appList.push(this.applicationbarcode);
//give focus to the tracking number after a batch has been made
document.addEventListener("change", function(appBar) {
if (appBar === "*AddToBatch*") {
this.appList = [];
this.shipperbarcode = document.querySelector(
"input[name=shippernumber]"
).value;
this.trackingbarcode = "";
let hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
// after entering a new tracking number pass the focus to the barcode input
if (hasFocus.value.length > 0) {
hasFocus = document.querySelector("input[name=appbarcode]");
hasFocus.focus();
} else {
hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
}
}
});
this.applicationbarcode = "";
this.applicationbarcode = this.applicationbarcode.replace(/[^0-9.]/g, "");
},
addedToBatch: function() {
this.addToBatch("*AddToBatch*");
},
// When the add to batch button is scanned
addToBatch: function(appBar) {
// open the modal if the counter is above 25. This will be rewritten to read from server as the 25 can differ
if (this.counter >= 25) {
UIkit.modal("#closeBatchDialog").show();
}
// if the counter is > 0 show the close batch button
if (this.counter > 0) {
this.finishBatch = true;
}
// If the app barcode is Add to Batch barcode give shipper # input field the value it already has
// and clear the tracking number field. ********** Must exist for click event
if (appBar === "*AddToBatch*") {
this.appList = [];
this.shipperbarcode = document.querySelector(
"input[name=shippernumber]"
).value;
this.trackingbarcode = "";
//give focus to the tracking number after a batch has been made
let hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
// after entering a new tracking number pass the focus to the barcode input
if (hasFocus.value.length > 0) {
hasFocus = document.querySelector("input[name=appbarcode]");
hasFocus.focus();
} else {
hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
}
}
},
// if the close shipper barcode is scanned
closeShipper: function(e) {
// if the barcode for close shipper is scanned
if (this.applicationbarcode === "*CloseShipper*") {
// clear all fields
this.appList = [];
this.shipperbarcode = "";
this.trackingbarcode = "";
// give the shipper id field focus
document.addEventListener("change", function() {
let hasFocus = document.querySelector("input[name=shippernumber]");
hasFocus.focus();
});
}
},
sendFocus: function(e) {
document.addEventListener("keydown", function(e) {
var input = e.target.nodeName.toLowerCase() === "input";
var form = e.target.form;
if (e.key === "Enter" && input) {
var index = Array.prototype.indexOf.call(form, e.target);
form.elements[index + 1].focus();
}
});
}
},
created() {
let that = this;
this.fetchBatches().then(function() {
that.sendFocus();
});
}
I commented as much as I could. The addApplication method is the one that validates that the barcode is a number or AddToBatch. If it's a number barcode, push it to the array as it is recognized as a normal barcode format. If it's reading AddToBatch, then clear the array (which later will put the array to the API), clear the tracking field and send the cursor to the tracking field to read a new tracking number
Any help will be very appreciated. I'm the only one here in this particular skillset and that sucks :( Thanks
P.S. No jQuery. ES6 preferably.
You have an empty return inside application, thats why it behaves wierd on "AddToBatch" condition, did you missed anything inside if condition or conditon should be like
this.applicationbarcode === "AddToBatch" && this.applicationbarcode === "CloseShipper"
if (
this.applicationbarcode === "*AddToBatch*" ||
this.applicationbarcode === "*CloseShipper*"
) {
this.applicationbarcode = "";
return;
} else {
this.counter += 1;
}

Change color of all occurrences of a character javascript/reactjs

I am working with reactjs have a form with multiple input fields and some of them have labels with an asterisk to indicate that the field is mandatory. I want to change the color of all the asterisks(*) to red for better visibility to the user. How can I change the color of all occurrences of the asterisk in my form to red at once?
PS : I don't want to put the asterisk in a span or a div. Rather I would like to write code so that every asterisk in the form gets the color red with a single piece of global code.
You should wrap asterisks in span element and assign some class. So you can give color to that class element in your css file.
Like this
<span class="required">*</span>
And in CSS
.required
{
color:red;
}
It's rather unclear what exactly you're trying to accomplish without having any code to reference. But I'm assuming what you're actually trying to highlight the asterisks (*) belonging to labels for fields that are empty during form-submission.
Try something like this: https://codesandbox.io/s/holy-leftpad-hw1oe
class App extends React.Component {
state = {
name: "",
password: "",
errors: false
};
handleOnChange = event => {
this.setState({
[event.target.name]: event.target.value
});
};
handleOnSubmit = event => {
event.preventDefault();
const { name, password } = this.state;
if (name.length === 0 || password.length === 0) {
this.setState({
errors: true
});
} else {
this.setState({
errors: false
});
}
};
render() {
const { name, password, errors } = this.state;
return (
<form onSubmit={this.handleOnSubmit}>
<label>
Name{" "}
<span
className={errors && name.length === 0 ? "error-label" : "label"}
>
(*)
</span>
</label>
<input name="name" onChange={this.handleOnChange} />
<label>
Password
<span
className={
errors && password.length === 0 ? "error-label" : "label"
}
>
(*)
</span>
</label>
<input name="password" onChange={this.handleOnChange} />
<button type="submit">Submit</button>
</form>
);
}
}

Unable to set default input radio checked if used with v-for

I am trying to add radio buttons to my code. Everything works fine except one thing. When I am using v-for loop for creating radios, the default radio is not getting checked. It works if, I put it outside the for loop.
I have tried this :-
:checked="index == 1"
and this ( as suggested in some answers ):-
:checked="{ index == 1 }"
But none of them is working for me.
Below is my template snippet:-
<div class="props-data">
<!-- <input type="radio" :checked="currentStep==1"> -->
<span v-for="(shape, index) in availableShapes" v-if="currentStep==1">
<div>
<input type="radio" :id="shape" :value="shape" v-model="selectedShape" :checked="index == 1">
<label :for="shape">{{shape}}</label>
</div>
</span>
</div>
Note:- steps-container is the main parent class where Vue instance is being created.
Below is my js code:-
window.onload = function(){
new Vue({
el: '#steps-container',
data: function() {
return {
currentStep: 1,
availableShapes: ['Rectangle','Circle','Square','Ellipse'],
selectedShape: undefined
};
},
methods: {
cancel: function(){
this.currentStep = 1;
jQuery('#main-action').text('Go to step '+ (this.currentStep+1));
},
nextStep: function(){
if( this.currentStep == 2 ){
jQuery('#main-action').text('Startover');
this.currentStep++;
}
else{
if( this.currentStep == 3 ){
this.currentStep = 1;
}
else{
this.currentStep++;
}
jQuery('#main-action').text('Go to step '+ (this.currentStep+1));
}
}
},
mounted: function(){
},
updated: function(){
}
});
}
Any help would be much appreciated.
You won't need to set the checked attr yourself. By using v-model="selectedShape" you have linked all the radio input with selectedShape.
You can already control the checked attr by controlling the value of selectedShape.
So set the initial value of selectedShape to the default value, and it will be checked by default.
<input type="radio" :id="shape" :value="shape" v-model="selectedShape"> (remove :checked="index == 1")
data: function() {
return {
//...
selectedShape: "THE DEFAULT VALUE"
};
},

Disable CheckBox Dynamically using JQuery

I have a collection of checkboxes within a form. I am looping through the collection to check and/or disable the checkboxes. The checking works fine; however, I am having an issue with checking if the checkbox is disabled or not. It always return false even when the checkbox is enabled. I looked at the code over and over, and I could not see a anything that could cause this to happen.
Partial HTML File
<label class="col-lg-3"><div style="padding-left:5px;">View Department</div></label>
<div class="col-lg-1"><input id="Accounting" name="Accounting" type="checkbox" /> </div>
<label class="col-lg-3"> Finance</label>
<div class="col-lg-1"><input id="Finance" name="Finance" type="checkbox" /></div>
<label class="col-lg-3"> Marketing</label>
<div class="col-lg-1"><input id="Marketing" name="Marketing" type="checkbox" /></div>
<div class="col-lg-12">
<hr style="width:100%;" />
</div>
//This is how I disable the checkbox
var collection = document.getElementById('DepartmentClassModal').getElementsByTagName('input');
if (typeof (e) !== 'undefined') {
if (e) {
switch (e) {
case 'Education':
for (var i = 0; i < collection.length ; i++) {
if ((collection[i].id == 'Accounting') || (collection[i].id == 'Finance')) {
collection[i].disabled = true
} else {
collection[i].disabled = false
}
}
break;
}
}
}
//The rendering HTML
<input checked="checked" id="Accounting" name="Accounting" type="checkbox" disabled>
//checking if the field is disabled or not
var isAccountingDisabled = $('#Accounting').is(':disabled');
//The above code always return false. Why is that?
I added a screen shot of the checkbox property showing that the checkbox is automatically checked and disabled. Even though the checkbox is rendering as disabled, the property does not show it as being disabled.
You can't have multiple elements with the same id. In your looping structure you can add the index of the loop also to the id, so that it will be unique. (Accounting1, Accounting2...)
Change your code to something like this
var checkBoxesCollection = $("#yourparentelement").find("input:checkbox[name='Accounting']");
$.each(checkBoxesCollection, function(){
if (this.disabled) {
};
});
http://jsfiddle.net/eanamztz/
Use === instead of ==
for (var i = 0; i < collection.length ; i++) {
if ((collection[i].id === 'Accounting') || (collection[i].id === 'Finance')) {
collection[i].disabled = true
} else {
collection[i].disabled = false
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
I was not able to read the property using $('#Accounting').is(':checked'); however, I was able to read them using the syntax below.
var collection = document.getElementById('DepartmentClassModal').getElementsByTagName('input');
$.each(collection, function (index, item) {
ListDepartments[item.name + "Disabled"] = item.disabled;
})

Categories

Resources