Can't type in input element of React application - input

I am creating a react application that is a replica of frogger and I have a form included for when you get a high score to input your name. But you can't type in the input box, no letters show up. Below is my code for the game over/high score divs:
{this.state.collision ? <div >Game Over! {this.checkHighScore() ?
<Modal
isOpen={true}
style={customStyles}
>
<div >
New High Score!
<form style={{zIndex: '9999'}}>
<input type="text" style={{zIndex: '1', color: 'black'}} onChange={(e) => this.onNameChange(e)} type="text" placeholder="Enter Name"/>
<input type="submit" text="Submit" onClick={(e) => this.highScoreSubmit(e)}></input>
</form>
</div>
</Modal>
:
<div></div>
}</div> : <div></div>}
As you can see I'm calling an onChange to store input value in state. I've tried console.log in the onchange function, but it's not registering any input. Also I've tried playing with z-index and making sure the color is black. It seems like something is interfering with event functions for some reason, but not sure what that would be. Thanks for any thoughts!

You most likely need to change onChange={(e) => this.onNameChange(e)} to onChange={(e) => this.onNameChange(e.target.value)} This is because you are passing an event to this.onNameChange, instead of a string.
In the future, don't hesitate to console.log things out. You knew it had something to do with your onChange method, so the next steps would be 1.) to find out if it is firing, and if e is what you expect, and 2.) to follow that through the call to this.onNameChange, logging from within that method to ensure it is being executed with the correct arguments.

Related

VueJs handle Form Submit on Enter press

I have a background in Angular. Starting with vue was an okay experience for me until I came across a problem which VueJS developers seem to have shit on and slid under the carpet.
How can we create a form in which user can press enter from an input field to submit the form
This was seriously disappointing.
and please if you know the answer be kind enough to post in the Official vue documentation as well.
*Note:
my workaround: I used v-on:keydown.enter.prevent='loginUser' on every input field.
is there any way to not use it this way ( on every input field).
With button type as submit as well, form gets submitted when Enter key is pressed on any input.
No explicit binding is required on keypress.
new Vue({
el: '#app',
data() {
return {
title: "Vue 2 -Form submission on Enter",
formInput:{
fname:'',
lname:'',
gender:'male'
}
};
},
methods:{
onSubmit(){
console.log('submitted', this.formInput)
}
}
})
.form{
display:flex;
flex-direction:column;
gap:10px;
max-width:200px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"><h2>{{title}}</h2>
<form v-on:submit.prevent="onSubmit" class="form">
<input v-model="formInput.fname" #keydown.enter.prevent placeholder="first name"/>
<input v-model="formInput.lname" placeholder="last name"/>
<div>
<input v-model="formInput.gender" name="gender" placeholder="Gender" type="radio" value="male"/>male
<input v-model="formInput.gender" name="gender" placeholder="Gender" type="radio" value="female"/>Female
</div>
<button type="submit">Submit</button>
<pre>{{formInput}}</pre>
</form>
</div>
I'd urge you to check out this page on the VueJS documentation.
It explains how to set events on certain interactions. For example, you can trigger a function call on pressing the Enter key within an input field by doing this:
<input type="text" #keyup.enter="submit">
This will call the submit() method when the Enter key is pressed and released (keyup). On press, you can use keydown instead.'
In fact, the example I've taken is directly from this section in the page I linked above.
EDIT: A pure-HTML way to do this is to set your input type as submit, which will allow Enter to submit the form
You need to wrap your inputs within <form> ... </form> tag

How to disable auto-complete or auto-fill in react-select?

How to disable auto-complete or auto-fill in react-select?
I need an answer without the involvement of the Input custom component.
Can you guys please help me to figure it out?
You can use custom Input component and can use that component with react-select.
Something like this:-
import Select, { components } from 'react-select'
const Input = ({ ...rest }) =>
<components.Input {...rest} autoComplete={'nope'} />
<Select {...rest} components={{ Input }} />
Chrome now ignores autoComplete="off" unless it is on the <form autocomplete="off"> tag.
So, that's why I'm using random string autoComplete="off"

How to change active color of Materialize label-icon in search input

I'm new to Materialize and I'm trying to change the active color of the Search and Close icons within a search box. When active, they appear black - I want them to appear white. The examples I've found predate Materialize 1.0. Any help would be greatly appreciated. Thanks!
<form action="" method="post">
<div class="input-field">
<input id="search" type="search" name="search" class="light-blue darken-3 white-text">
<label class="label-icon" for="search"><i class="material-icons">search</i></label>
<i class="material-icons">close</i>
</div>
</form>
https://codepen.io/Cormang/pen/oNvqmmM
By default you can make your search icon active by adding active class to <label>. But it seems there is another event that makes its changes. So one of the ways to addressing this issue is using focusin and focusout.
Add a onfocusin to <input> and call a function like this :
function changeColorOnFocus() {
document.querySelector(".material-icons").style.color = "white";
}
Use a onfocusout and call a function like this to change the icon's color.

How to reset vue modal component working with vue-show to use autofocus

I made modal component using v-show options live below.
<registerModal v-show="register.etcCompanyVisible" />
Thus, when register.etcCompanyVisible is true, this modal appears.
And this modal has some input like this.
<input type="text" v-model="etcCompanyName" placeholder="name" autofocus />
When this modal is opened at first time, the autofocus works well.
And then, this modal can be closed with cancel button by changing register.etcComapnyVisible to false.
<button class="btn secondary" v-on:click="etcCompanyVisibleClosed()">Cancel</button>
When I open modal again, the autofocus doesn't work. I think it needs some reset option for this modal, but I don't know how it can be done.
Could you give me some recommendation? Thank you so much for reading.
My understanding is that the autofocus attribute is only reliable on page load, so you need to handle the focus event yourself.
The easiest way to do this is to put a ref on your input.
<input ref="companyName" type="text" v-model="etcCompanyName" placeholder="name"/>
Then when you launch your modal, maybe you are using a button, call the focus on that $ref.
<template>
...
<button #click="focusInput">launch modal</button>
...
</template>
<script>
...
methods:{
foucusInput() {
this.$refs.companyName.focus();
}
}
Note that you could use the same method to dynamically focus inputs in a certain order. Here is a fiddle demonstrating that using button clicks but you could easily use this to move from one input to the next automatically after a certain condition is met.

Remove validation in angular 4 when it's not render in NgIf

I want to remove validation for which control is not rendered by using NgIf. I was try to use directive to remove with hidden control but cannot do the same because it not render in template. So I can not check formControlName with ElementRef in directive. Here is ts file
this.form = this._fb.group({
text1: ['', Validators.required],
text2: ['', Validators.required]
});
and template
<form[formGroup]="form">
<input type="text" formControlName="text1">
<div *ngIf="false">
<input type="text" formControlName="text2">
</div>
I want to remove Validation of text2 dynamically and globally. Not remove validator in ts file.
This Angular source GitHub Issue comment by Kara seems extremely relevant, and illustrates how you might solve the problem by treating the reactive model as "source of truth" and create your ngIf expression off of that source of truth, instead of the reverse. This shows it's by design and you have to make some effort not to mix up template-driven and reactive form ideas.
https://github.com/angular/angular/issues/7970#issuecomment-228624899
Thanks for taking the time to describe the problem. I took a look at
your example code, and it seems that you are using the reactive form
directives (a.k.a "model-driven" directives: ngFormModel, etc), but a
template-driven strategy. The fact that the ngIf does not remove the
control from the form's serialization and validation is actually by
design, and here's why.
In each form paradigm - template-driven and reactive - there can only
be one source of truth for the list of active controls. In the
template-driven paradigm, the source of truth is the template. In the
reactive equivalent, the source of truth is the form model created in
the parent component. The DOM does not dictate the state of your form.
For this reason, if you remove form control elements from the DOM
while using a reactive approach, the form controls are not necessarily
changed in the source of truth unless you want them to be. You can
choose to update the controls imperatively by calling
this.form.removeControl('controlName'), or you can choose to keep the
controls in your form. This flexibility allows you to add or remove
inputs from the DOM temporarily while keeping their form values
serialized (e.g. if you have a number of collapsible sections to your
form, you can remove sections on collapse without impacting the value
of your form). We don't want to restrict this flexibility and
complicate ownership by forcing the model to always match the DOM.
So in your case, if you choose a reactive strategy, you'll want to
invert your logic to rely on the source of truth - the model.
Specifically, this means removing the control imperatively in the
model by calling this.form.removeControl('name') when the button is
clicked. Then, the ngIf should depend on the control's presence in the
model with *ngIf="form.contains('name')", rather than the other way
around. See example plunker here:
http://plnkr.co/edit/V7bCFLSIEKTuxU9jcp6v?p=preview
It's worth noting that if you're still using beta.14 (as in your
plunker), you'll need to call this.form.updateValueAndValidity()
manually. This requirement was removed in #9097, so versions after
RC.2 don't require the call.
Another option is to convert to a template-driven strategy (no
ngFormModel), which will remove the control from the form when it's
destroyed from the template. Example:
http://plnkr.co/edit/s9QWy9T8azQoTZKdm7uI?p=preview
I'm going to close this issue as it works as intended, but I think we
could make the experience a lot friendlier. A good start would be some
more cookbooks and guides in the documentation.
When the condition property is changed then call the method dynamically to set and remove the validation. for example,
whenConditionChanges(condition:boolean){
if(!condition){
this.form.controls["text2"].setValidators([Validators.required]);
this.form.controls["text2"].updateValueAndValidity();
} else {
this.form.controls["text2"].setValidators(null);
this.form.controls["text2"].updateValueAndValidity();
}
}
Since, your formcontrol text2 is dependent on some condition. it should not be as required control. So you reactive form control should be
this.form = this._fb.group({
text1: ['', Validators.required],
text2: ['',]
});
If there is scenario, where you want to ensure that text should be required whenever it's present in dom then use custom validators in angular. Refer documentation of the same for your implementation.
Here the Example: on runtime you can update validators based on checkbox value.you can set field as required and remove also.
http://plnkr.co/edit/YMh0H61LxPGCFtm9Yl13?p=preview
What i did (and work for me), create an alternative formgroupcontrol with another button [disabled], manage the *ngIf for the button and for the form.
<mat-step [stepControl]="listBrandFormGroup">
<form [formGroup]="listBrandFormGroup">
<ng-template matStepLabel>Define tu marca</ng-template>
<div class="heading">¡ Haber ! Definamos tu marca</div>
<div class="subheading">Estamos a punto de hacer magia, solo necesitamos lo siguiente:</div>
<div class="content" fxLayout="column" fxLayoutGap="8px" *ngIf="listBrand.length > 0">
<mat-form-field fxFlex="auto">
<mat-select name="brand_id" formControlName="brand_id" placeholder="Selecciona una marca existente" (selectionChange)="setBrand($event.value);">
<mat-option [value]="0">Crear una nueva marca</mat-option>
<mat-option *ngFor="let marca of listBrand" [value]="marca.id">{{marca.display_name}}</mat-option>
</mat-select>
<mat-hint>{{descripBrand}}</mat-hint>
</mat-form-field>
</div>
</form>
<form [formGroup]="brandFormGroup">
<div class="content" fxLayout="column" fxLayoutGap="8px" *ngIf="idBrand === 0">
<mat-form-field>
<mat-label>Marca</mat-label>
<input matInput formControlName="display_name" required>
<mat-hint>Ese increíble y único nombre, ¡ tú sabes !</mat-hint>
</mat-form-field>
<mat-form-field fxFlex="grow">
<mat-label>Descripción</mat-label>
<textarea matInput formControlName="descrip" required></textarea>
<mat-hint>¿ Cuéntanos de que se trata ?</mat-hint>
</mat-form-field>
<mat-label>Logo</mat-label>
<input type="file" name="photo" ng2FileSelect required formControlName="display_logo" />
</div>
<div class="actions" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="8px">
<button mat-button type="button" (click)="stepper.reset()" [disabled]="brandFormGroup.pristine"
color="primary">RESET
</button>
<button mat-raised-button matStepperNext color="primary" [disabled]="brandFormGroup.invalid" *ngIf="idBrand === 0">SIGUIENTE</button>
<button mat-raised-button matStepperNext color="primary" [disabled]="listBrandFormGroup.invalid" *ngIf="idBrand > 0">SIGUIENTE</button>
<button mat-raised-button matStepperNext color="primary" [disabled]="listBrandFormGroup.invalid" *ngIf="idBrand > 0" (click)="launch();"><i class="material-icons">launch</i>LANCÉMONOS</button>
</div>
</form>
</mat-step>