set ngModel value to null after changing selected option - angular-reactive-forms

i have a form which contains a select option and a div section depends on the selected option. in the select option if i choose 1 for exemple , an input will be displayed
component.ts
types : any[] = [
{ value : '1'},
{ value : '2'},
{ value : '3'}
];
createForm = this.fb.group({
firstInput:['',Validators.required],
secondInput:['',Validators.required],
thirdInput:['',Validators.required],
});
component.html
<select class="form-control" [value]="selected"[(ngModel)]="selectedValue">
<option *ngFor="let x of types">{{x.value}}</option>
</select>
<div *ngIf="selectedValue == '1'">
<label for="1" class="control-label">1</label>
<input id="1" class="form-control" type="text" formControlName="firstInput">
</div>
<div *ngIf="selectedValue == '2'">
<label for="2" class="control-label">2</label>
<input id="2" class="form-control" type="text" formControlName="secondInput">
</div>
<div *ngIf="selectedValue == '3'">
<label for="3" class="control-label">3</label>
<input id="3" class="form-control" type="text" formControlName="thirdInput">
</div>
all the fields are required, my problem is : when i choose "1" for exemple without filling the input of "1" then i change for the second choice "2" and fill it, i can't submit the form because the fielControllName "firstInput" is empty despite being invisible, so i need to clear the selected value of ngModel ( as i think ) with each change.

So Initially your form must be like:
createForm = this.fb.group({
selectedValue:[null,Validators.required],
firstInput:[null],
secondInput:[null],
thirdInput:[null],
});
Your HTML code:
<form [formGroup]="createForm">
<select class="form-control" formControlName="selectedValue">
<option *ngFor="let x of types" value="{{x.value}}">{{x.value}}</option>
</select>
<div *ngIf="createForm.value.selectedValue== '1'">
<label for="1" class="control-label">1</label>
<input id="1" class="form-control" type="text" formControlName="firstInput">
</div>
<div *ngIf="createForm.value.selectedValue== '2'">
<label for="2" class="control-label">2</label>
<input id="2" class="form-control" type="text" formControlName="secondInput">
</div>
<div *ngIf="createForm.value.selectedValue== '3'">
<label for="3" class="control-label">3</label>
<input id="3" class="form-control" type="text" formControlName="thirdInput">
</div>
</form>
Then you must have on change Function:
OnChange() {
this.createForm.get('selectedValue').valueChanges.subscribe(
val => {
if (val==1) {
this.createForm.get('firstInput').setValidators([Validators.required]);
this.createForm.controls['firstInput'].updateValueAndValidity();
this.createForm.get('secondInput').setValidators([]);
this.createForm.controls['secondInput'].updateValueAndValidity();
this.createForm.get('thirdInput').setValidators([]);
this.createForm.controls['thirdInput'].updateValueAndValidity();
}
else if (val==2) {
this.createForm.get('firstInput').setValidators([]);
this.createForm.controls['firstInput'].updateValueAndValidity();
this.createForm.get('secondInput').setValidators([Validators.required]);
this.createForm.controls['secondInput'].updateValueAndValidity();
this.createForm.get('thirdInput').setValidators([]);
this.createForm.controls['thirdInput'].updateValueAndValidity();
}
else if (val==3) {
this.createForm.get('firstInput').setValidators([]);
this.createForm.controls['firstInput'].updateValueAndValidity();
this.createForm.get('secondInput').setValidators([]);
this.createForm.controls['secondInput'].updateValueAndValidity();
this.createForm.get('thirdInput').setValidators([Validators.required]);
this.createForm.controls['thirdInput'].updateValueAndValidity();
}
}
)
}
if you want to make value null you can use:
this.createForm.patchValue({
firstInput:null,
secondInput:null,
thirdInput:null,
})

Related

How do I show a message by opening a kendo popup?

In my form, there are 3 input values ​​in the period line. If all of them are empty or zero, I want to give a warning in the kendo popup before clicking the button.If a non-zero value is entered for any of them, it will not give an error.
3 input values for period in form
My code is as below :
<form id="formPlan" onsubmit="return hasValue()" class="form-horizontal form-group-sm" data-toggle="validator">
<div class="form-group required">
<label for="inPeriod" class="control-label col-xs-3">#ln.label_period:</label>
<div class="col-xs-4 input">
<div class="row">
<div class="col-xs-4">
<input type="number" id="inPeriod_day" name="Period" class="form-control" max="365" step="any" maxlength="2" style="width:100%">
</div>
<div class="col-xs-4">
<input type="number" id="inPeriod_hour" name="PeriodHour" class="form-control" max="23" step="any" maxlength="2">
</div>
<div class="col-xs-4">
<input type="number" id="inPeriod_minute" name="PeriodMinute" class="form-control" max="59" step="any" maxlength="2">
</div>
</div>
</div>
</form>
<div id="popup">Periods can't be blank!</div>
<script>
$("#popup").kendoPopup({
animation: {
close: {
effects: "fadeOut zoom:out",
duration: 300
},
open: {
effects: "fadeIn zoom:in",
duration: 300
}
}
});
function hasValue() {
var period = document.forms["formPlan"]["Period"].value;
var periodhour = document.forms["formPlan"]["PeriodHour"].value;
var periodminute = document.forms["formPlan"]["PeriodMinute"].value;
if (!period && !periodhour && !periodminute) {
$("#popup").data("kendoPopup").open();
return false;
}
return true;
}
</script>

Disabling Submit button until required fields are filled using JavaScript

I am trying to disable the form Submit button until the required fields are filled. However my code does not seem to be looping properly through the condition as any input enables the submit button. https://codepen.io/ldanneman/pen/MWyGJMx?editors=0010
<form>
<div class="form-box">
<label for="fname">First Name<span>*</span></label>
<input type="text" id="fname" name="First Name" placeholder="First Name" required><br>
<label for="lname">Last Name</label>
<input type="text" id="lname" name="Last Name" placeholder="Last Name"><br>
<label for="email">Email<span>*</span></label>
<input type="email" id="email" name="Email" placeholder="abc#client.com" required><br>
<label for="phone">Phone<span>*</span></label>
<input type="tel" id="phone" name="Phone" placeholder="111-222-3333" required><br>
<label for="comments">Comments<span>*</span></label>
<textarea id="comments" name="comments" placeholder="Comments" required></textarea><br>
<button class="submit" type="submit">Submit</button>
</div>
</form>
</div>
JavaScript:
let requiredInputs = document.querySelectorAll("[required]");
let submitButton = document.querySelector(".submit");
submitButton.disabled = true;
for(let i = 0; i < requiredInputs.length; i++){
requiredInputs[i].addEventListener("input", buttonState)
};
function buttonState() {
if (requiredInputs.value === "") {
submitButton.disabled = true;
} else {
submitButton.disabled = false;
}
}
You're close, but the code in your callback, buttonState() is insufficient to accomplish what you want. It is checking for the value of requiredInputs which is a collection of HTML Input elements. What you want to do is loop through each item in that collection and check if their value is set:
function buttonState() {
submitButton.disabled = Array.from(requiredInputs).some(x => x.value === '');
}
The code above will use some() which will returns true if any callback results in true, in the case if the value of an input is an empty string.

How to get selected values to input values (as objects) in Spring + Thymeleaf?

View: modAnimal.html (this is the first part of the view, after it there are input values in hidden div)
<form th:action="#{/animales/preModAnimal}" th:object="${animal}" method="post" enctype="multipart/form-data" id="formPreModAnimal">
<!-- INPUT TIPO DE ANIMAL -->
<label>Animal</label>
<input type="radio" th:field="*{tipo}" th:value="*{tipo.PERRO}" required />
<label>🐕</label>
<input type="radio" th:field="*{tipo}" th:value="*{tipo.GATO}" required />
<label>🐈</label>
<!-- INPUT SEXO DEL ANIMAL -->
<label>Sexo</label>
<input type="radio" th:field="*{sexo}" th:value="*{sexo.MACHO}" required />
<label>♂️</label>
<input type="radio" th:field="*{sexo}" th:value="*{sexo.HEMBRA}" required />
<label>♀️</label>
<!-- INPUT SELECT ANIMAL -->
<label for="selectAnimal">Animal</label>
<select th:fragment="animales" id="selectAnimal" required
class="form-control">
<option value="" selected="selected">Selecciona animal</option>
<option th:each="i : ${animales}"
th:text="${i.emojiTipo} + ' ' + ${i.emojiSexo} + ' - ' + ${i.nombre} + ' - ' + ${i.raza} + ' - ' + ${i.provincia.provincia} + ' (' + ${i.poblacion} + ')'"
th:value="${i.id}"></option>
</select>
</form>
Depending on the selected radios, the select drop-down will be loaded with the desired values.
This is done with jQuery
funcionesCheck_jQuery.js
$(document).ready(function() {
$('[name=tipo], [name=sexo]').change(function() {
$("#selectAnimal").load('/animales/checktiposexo', $('#formPreModAnimal :input[type=radio]').serialize());
});
});
And this is the controller
AnimalesController.java
#GetMapping("/modAnimal") public String pagMod(Model model) {
Animal animal = new Animal();
model.addAttribute("animal", animal);
Sexo[] opcionesSexo = Sexo.values();
model.addAttribute("sexos", opcionesSexo);
Tipo[] opcionesTipo = Tipo.values();
model.addAttribute("tipos", opcionesTipo);
return "animales/modAnimal";
}
#GetMapping("/checktiposexo")
public String filtroTipoSexo(Model model, #RequestParam(name = "tipo", required = false) Tipo tipo,
#RequestParam(name = "sexo", required = false) Sexo sexo) {
List<Animal> listaAnimales;
if (tipo == null && sexo == null) { // not working, i wanted this to act different, but nvm
listaAnimales = animalesRepo.findAll();
model.addAttribute("animales", listaAnimales);
} else if (tipo != null && sexo == null) {
listaAnimales = animalesRepo.findAllAnimalesByTipoOrSexo(tipo, sexo);
model.addAttribute("animales", listaAnimales);
} else if (tipo == null && sexo != null) {
listaAnimales = animalesRepo.findAllAnimalesByTipoOrSexo(tipo, sexo);
model.addAttribute("animales", listaAnimales);
} else {
listaAnimales = animalesRepo.findAllAnimalesByTipoAndSexo(tipo, sexo);
model.addAttribute("animales", listaAnimales);
}
return "animales/modAnimal :: animales"; //I'm returning animales as fragment
}
Then I want to fill some input values with the values given in the selected option in the same view mentioned at begin of the post.
Everytime the selected option changes, these inputs will re-show again. They're in a div (#modificarOculto) initially hidden at begin.
funcionesCheck_jQuery.js
$(document).ready(function() {
$( "#modificarOculto" ).hide();
$("[name=tipo], [name=sexo], #selectAnimal").change(function() {
$('#modificarOculto').hide('300');
$("#selectAnimal").change(function() {
inputSelectAnimal = $("#selectAnimal")[0];
selectAnimal = $("#selectAnimal").val();
if(selectAnimal>0){
$('#modificarOculto').show('slow');
}else if(selectAnimal==0){
$('#modificarOculto').hide('slow');
}
});
});
});
Remember, this is the part of the view below the view at begin. I want to load the selected values in these inputs.
modAnimal.html (again)
<div class="row cajita" id="modificarOculto">
<form th:action="#{/animales/modAnimal-submit}" id="formModAnimal"
th:object="${animal}" method="post" enctype="multipart/form-data">
<label >Nombre</label>
<input type="text" th:field="*{nombre}" class="form-control"
placeholder="Nombre del animal" required minlength=3
maxlength=50 />
<label>Animal</label>
<input type="radio" th:field="*{tipo}" th:value="*{tipo.PERRO}"required />
<label>🐕</label>
<input type="radio" th:field="*{tipo}" th:value="*{tipo.GATO}" required />
<label>🐈</label>
<label>Sexo</label>
<input type="radio" th:field="*{sexo}" th:value="*{sexo.MACHO}" required />
<label>♂️</label>
<input type="radio" th:field="*{sexo}" th:value="*{sexo.HEMBRA}" required />
<label>♀️</label>
<!-- INPUT PROVINCIA ANIMAL -->
<label>Provincia</label>
<select id="provincia" name="provincia" required>
<option value="">Load the selected provincia</option>
<option th:each="i : ${provincias}" th:text="${i.provincia}"
th:value="${i.id}">
</select>
<button type="submit" id="botonModificar">Modificar</button>
</form>
</div>
I know I need a form to submit the new values ("formModAnimal"), but... I know I don't need the form of begin ("formPreModAnimal"). What I don't really know if I would need to englobe the whole view (select part + input part) in a form together.
How could I send the data as object values from the selected value to input values? Is there any smart way to do it with Thymeleaf?
May I be able to associate the selected value to a fragment and send it to the form "formModAnimal" and use it as animal.attribute? That would be very comfortable.
How would you do this?
I've deleted all the bootstrap divs and classes for your overview comfort. I hope everything is clear for you!
Thanks in advance!
Okay, I've resolved it.
This is my new jQuery function in funcionesCheck_jQuery.js, where I load in div $('#modificarOculto') the serialized results of the selected drop-down $("#selectAnimal").
(I don't know why can't I just take the id of the drop-down, or why #RequestParam("selectAnimal") can't take it from the view directly...)
$(document).ready(function() {
//$("#modificarOculto").hide();
$("[name=tipo], [name=sexo], #selectAnimal").change(function() {
$('#modificarOculto').hide('300');
$("#selectAnimal").change(function() {
inputSelectAnimal = $("#selectAnimal")[0];
selectAnimal = $("#selectAnimal").val();
if (selectAnimal > 0) {
$('#modificarOculto').show('slow');
$('#modificarOculto').load('/animales/animalid', $("#selectAnimal").serialize());
} else if (selectAnimal == 0) {
$('#modificarOculto').hide('slow');
}
});
});
});
This is managed in the controller AnimalController.java: #RequestMapping("/animalid"), which will return a thymeleaf fragment with the selected animal values.
#RequestMapping("/animalid")
public String getAnimalByID(#RequestParam(name = "selectAnimal", required = false) int idAnimal, Model model) {
Animal animalModelo = new Animal();
model.addAttribute("animal", animalModelo);
Esterilizado[] opcionesEsterilizado = Esterilizado.values();
model.addAttribute("esterilizados", opcionesEsterilizado);
List<Provincia> listaProvincias = provinciasRepo.findAll();
model.addAttribute("provincias", listaProvincias);
Optional <Animal> animal = animalesRepo.findOneAnimalById(idAnimal);
if (animal.isPresent()) {
model.addAttribute("selectedAnimal", animal.get());
} else {
// ERROR?
}
return "animales/modAnimal :: selectedAnimal";
}
And finally, this is the second part of my View. I insert the Thymeleaf fragment inside the form and I use it as object too. This form is also ready to submit the given data to database (mapped). Now I'm working on updating the data instead inserting.
<div class="row cajita" id="modificarOculto">
<div class="col-md-9 offset-1">
<form th:action="#{/animales/modAnimal-submit}" id="formModAnimal"
th:object="${selectedAnimal}" method="post" enctype="multipart/form-data"
class="was-validated" th:fragment="selectedAnimal">
<th:block th:if="${selectedAnimal != null}">
<!-- INPUT NOMBRE ANIMAL -->
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="nombre">Nombre</label>
<div class="col-sm-10">
<input type="text" th:name="nombre" th:value="${selectedAnimal.getNombre()}" class="form-control"
placeholder="Nombre del animal" required minlength=3
maxlength=50 />
</div>
</div>
<div class="form-group row">
<!-- INPUT TIPO DE ANIMAL -->
<label class="col-sm-2 col-form-label">Animal</label>
<div class="col-sm-1">
<div class="form-check">
<input type="radio" th:name="tipo" th:value="${selectedAnimal.tipo.PERRO}" th:checked="${selectedAnimal.getTipo()} == ${selectedAnimal.tipo.PERRO}"
class="form-check-input" required > <label class="form-check-label">🐕</label>
</div>
<div class="form-check">
<input type="radio" th:name="tipo" th:value="${selectedAnimal.tipo.GATO}" th:checked="${selectedAnimal.getTipo()} == ${selectedAnimal.tipo.GATO}"
class="form-check-input" required > <label class="form-check-label">🐈</label>
</div>
</div>
<!-- INPUT SEXO DEL ANIMAL -->
<label class="col-sm-1 col-form-label">Sexo</label>
<div class="col-sm-1">
<div class="form-check">
<input type="radio" th:name="sexo" th:value="${selectedAnimal.sexo.MACHO}" th:checked="${selectedAnimal.getSexo()} == ${selectedAnimal.sexo.MACHO}"
class="form-check-input" required > <label class="form-check-label">♂️</label>
</div>
<div class="form-check">
<input type="radio" th:name="sexo" th:value="${selectedAnimal.sexo.HEMBRA}" th:checked="${selectedAnimal.getSexo()} == ${selectedAnimal.sexo.HEMBRA}"
class="form-check-input" required > <label class="form-check-label">♀️</label>
</div>
</div>
<!-- INPUT RAZA -->
<label class="col-sm-1 col-form-label" for="nombre">Raza</label>
<div class="col-sm-6">
<input type="text" th:name="raza" th:value="${selectedAnimal.getRaza()}" class="form-control"
placeholder="Raza del animal" required minlength=3 maxlength=100 />
</div>
</div>
<div class="form-group row">
<!-- INPUT FECHA DE NACIMIENTO -->
<label class="col-sm-2 col-form-label" for="fnac">Fecha de
nacimiento</label>
<div class="col-sm-4">
<input type="date" th:name="fnac" th:id="fnac" th:value="${selectedAnimal.getFnac()}" class="form-control"
min="1990-01-01" required />
</div>
<!-- INPUT ESTERILIZADO -->
<label class="col-sm-2 col-form-label">Esterilizado</label>
<div class="col-sm-4">
<th:block th:each="i : ${esterilizados}">
<div class="form-check">
<input type="radio" th:name="esterilizado" th:id="'esterilizado'+${iStat.index+1}" required
th:value="${i}" class="form-check-input" th:checked="${selectedAnimal.getEsterilizado() == i}" > <label
class="form-check-label" th:for="'esterilizado'+${iStat.index+1}"
th:text="${#strings.capitalize(#strings.toLowerCase(i))}">Esterilizado</label>
</div>
</th:block>
</div>
</div>
<div class="form-group row">
<!-- INPUT PROVINCIA ANIMAL -->
<label class="col-sm-2 col-form-label" for="provincia">Provincia</label>
<div class="col-sm-4">
<select id="provincia" th:name="provincia" required
class="form-control">
<option th:each="i : ${provincias}" th:text="${i.provincia}"
th:value="${i.id}"
th:selected="${selectedAnimal.getProvincia().getId() == i.id}">
</select>
<!-- Si fuera un valor enum <td><select th:field="*{provincia}">
<option th:each="i : ${provincias}" th:text="${i.toString()}"
th:value="${i}"></option></select></td>-->
</div>
<!-- INPUT POBLACION ANIMAL -->
<label class="col-sm-2 col-form-label" for="fnac">Población</label>
<div class="col-sm-4">
<input type="text" th:name="poblacion" th:value="${selectedAnimal.getPoblacion()}" class="form-control"
required minlenght=2 maxlength=50 />
</div>
</div>
<!-- INPUT FOTO ANIMAL -->
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="file">Foto</label>
<div class="col-sm-10">
<input type="file" name="file" accept="image/*"
class="form-control-file" id="validatedCustomFile" required />
<div class="invalid-feedback">Ningún archivo seleccionado</div>
</div>
<!-- INPUT FOTO EN LAS SOMBRAS -->
<label for="foto" style="display: none;">Foto</label> <input
type="text" th:name="foto"
th:value="${selectedAnimal.getFoto()}" maxlength=200
style="display: none;" />
</div>
<!-- INPUT DESCRIPCION ANIMAL -->
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="descripcion">Descripción</label>
<div class="col-sm-10">
<textarea class="form-control" required rows="5" cols="50"
th:name="descripcion" minlength=50 maxlength=255
th:text="${selectedAnimal.getDescripcion()}" th:value="${selectedAnimal.getDescripcion()}"
placeholder="Historia, personalidad, enfermedades, comportamiento con otras mascotas"></textarea>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<button type="submit" class="btn btn-success float-right"
id="botonUpdateAnimal">Actualizar</button>
</div>
</div>
<div th:if="${message}" th:text="${message}"
th:class="${'alert ' + alertClass}" ></div>
</th:block>
</form>
</div>
</div>

multimple select2 with laravel vue js not working

i want to make dynamic form .so for that i tried foreach loop .everything going fine without select options. For making classname or id name unique i want place a index value but cant not place index value.take a look below:
<div class="form-group m-form__group row " v-for="(pack,index) in packs">
<div class="col-lg-3">
<label>SKU: #{{ index }}</label>
<input v-model="pack.sku" type="text" name="name" class="form-control m-input" placeholder="SKU">
</div>
<div class="col-lg-3">
<label>Unit:</label>
<select class="form-control select2 #{{ index }}" name="unit" v-model="pack.unit" >
<option value="0">KG</option>
<option value="1">ML</option>
<option value="2">Liter</option>
</select>
</div>
<div class="col-lg-3">
<label>Size:</label>
<input v-model="pack.size" type="number" name="name" class="form-control m-input" placeholder="Size">
</div>
<div class="col-lg-3">
<label>Barcode:</label>
<input v-model="pack.barcode" type="number" name="barcode" class="form-control m-input" placeholder="Barcode">
</div>
</div>
you need to reload select2.
html markup:
<select class="form-control select2 #{{ index }}" name="unit" v-model="pack.unit" id="unit">
<option value="0">KG</option>
<option value="1">ML</option>
<option value="2">Liter</option>
</select>
Vuejs code:
...
components: {
},
mounted() {
setTimeOut(() => {
let unit = $('#unit'); // or document.querySelector('#unit');
unit.select2();
}, 100);
},

AngularJS Slightly Advanced Validation / Bootstrap3 Style

I am in the process of learning AngularJS, still at the most basic stages of form validation. I followed the official tutorial here, and managed to get the validation working like they have, where if input is invalid, the background changes colour.
That is all nice and counts as an important step in my learning, but how do I move a little further and have the validation add / remove CSS classes required by Bootstrap to show visual cues?
Here is my HTML code:
<form novalidate class="css-form">
<div class="form-group">
<label class="control-label" for="fname">First Name</label>
<input type="text" id="fname" placeholder="First Name" class="form-control" ng-model="user.fname" required >
</div>
<div class="form-group">
<label class="control-label" for="lname">Last Name</label>
<input type="text" id="lname" placeholder="Last Name" class="form-control" ng-model="user.lname" required >
</div>
<div class="form-group">
<label class="control-label" for="email">Email</label>
<input type="email" id="email" placeholder="Email" class="form-control" ng-model="user.email" required >
</div>
<div class="form-group">
<label class="control-label" for="password">Password</label>
<input type="password" id="password" placeholder="Password" class="form-control" ng-model="user.password" required >
</div>
<div class="form-group">
<label class="control-label" for="emailpref">Want annoying emails?</label>
<select class="form-control" ng-model="user.emailpref" required>
<option value="Null">Please Select</option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
In the Bootstrap3 documentation, it says that if I need to show a valid state, I must add a CSS class of has-success like so:
<div class="form-group has-success">
<label class="control-label" for="fname">First Name</label>
<input type="text" id="fname" placeholder="First Name" class="form-control" ng-model="user.fname" required >
</div>
How can I get my AngularJS validation to do that? At the moment, my AngularJS is as follows:
function UserCtrl($scope) {
$scope.master = {};
$scope.user = { fname: "J", lname: "Watson", password: "test", email: "j.watson#world.com", emailpref: "Yes" };
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
To add dynamic classes based on field validation you need to do two things
Give your form a name
`<form novalidate class="css-form" name="form1">`
Give each input field a name too. You can then use expression to determine state of error of a field
<div class="form-group has-success" ng-class="{'has-success':form1.fname.$invalid}">
<label class="control-label" for="fname">First Name</label>
<input type="text" id="fname" placeholder="First Name" class="form-control" ng-model="user.fname" required name="fname">
</div>
Please go through the form guide http://docs.angularjs.org/guide/forms for more details.
You can use angular-validator.
Disclaimer: I am the author of angular-validator

Resources