I have a form that I need the additional description input to show when 'other' is selected from the dropdown, however with the current function this only works on the second selection.
It currently works if a section is made, then cleared and then 'Other' is selected. I need this to fire and display the other box on the first click if required by the user.
HTML --
<form class="form-horizontal" [formGroup]="unableToScanForm" *ngIf="!loading" (ngSubmit)="onSubmit()">
<div class="container">
<div class="card-body">
<div class="form-group row">
<label class="col-md-4 col-form-label" for="reasonType"><strong>Reason*</strong></label>
<div class="col-md-12">
<ng-select id="reasonType" name="reasonType"
placeholder="Select a reason..."
labelForId="reasonType"
formControlName="reasonType"
[multiple]="false"
[hideSelected]="true"
[closeOnSelect]="true"
[items]="reasonType"
[searchable]="false"
bindLabel="type"
bindValue="type"
[ngClass]="{ 'is-invalid': submitted && f.reasonType.errors }">
</ng-select>
<div *ngIf="submitted && f.reasonType.errors" class="invalid-feedback">
Please select a reason.
</div>
</div>
</div>
<div class="form-group row" *ngIf="showAdditionalInfo">
<label class="col-md-4 col-form-label" for="reasonDescription"><strong>Additional Information*</strong></label>
<div class="col-md-12">
<textarea
rows="3"
class="form-control"
id="reasonDescription"
formControlName="reasonDescription"
[ngClass]="{ 'is-invalid': submitted && f.reasonDescription.errors }">
</textarea>
<div *ngIf="submitted && f.reasonDescription.errors" class="invalid-feedback">
Please detail a description of the reason.
</div>
</div>
</div>
</div>
</div>
</form>
TS --
reasonSelection(): void {
this.unableToScanForm.valueChanges.subscribe(value => {
if (value.reasonType === 'Other') {
this.showAdditionalInfo = true;
}
});
}
Suppose you have to start listen changes with the first form value:
reasonSelection(): void {
this.unableToScanForm.valueChanges
.pipe(startWith(this.unableToScanForm.value))
.subscribe(...);
}
Related
Using JQuery I would like to check the value of an input, if it equals Complete I would like to add the Bootstrap class is-valid to that input, and all the other inputs on the same row.
Something like this (pseudo code);
if wb_status_reg = Complete {
// add is-valid to all row inputs / select boxes
}
I should note that sometimes the row will contain a select box, not just text inputs. Also, I'm unable to edit the html as it's being generated by a form builder component (in a CMS).
My code is currently working but I know it's too long and could be improved. In my code i'm showing one form-row but I actually have many more, so I need to duplicate this a few more times.
How can I achieve this in a more efficient way?
jQuery(document).ready(function($) {
var wb_stage_reg = $('#wb_stage_reg');
var wb_status_reg = $('#wb_status_reg');
var wb_date_reg = $('#wb_date_reg');
setIsValid($);
});
function setIsValid($) {
wb_stage_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_stage_reg).addClass("is-valid") : "";
wb_status_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_status_reg).addClass("is-valid") : "";
wb_date_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_date_reg).addClass("is-valid") : "";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col-3">
<div class="form-group rsform-block-wb-stage-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_stage_reg" name="form[wb_stage_reg]" type="text" value="Registration"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-status-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_status_reg" name="form[wb_status_reg]" type="text" value="Complete"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-date-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_date_reg" name="form[wb_date_reg]" type="text" value="2020-06-08 09:41:40"><span></span>
</div>
</div>
</div>
</div>
</div>
Something like this:
You need to change ID to class on all fields
Since you cannot, I use the name instead:
$(function() {
$("[name='form[wb_status_reg]']").each(function() {
const $parent = $(this).closest(".form-row");
const complete = this.value === "Complete";
$parent.find("[name='form[wb_date_reg]'], [name='form[wb_stage_reg]']").toggleClass("is-valid",complete)
})
});
.is-valid { color:green}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col-3">
<div class="form-group rsform-block-wb-stage-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_stage_reg" name="form[wb_stage_reg]" type="text" value="Registration"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-status-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_status_reg" name="form[wb_status_reg]" type="text" value="Complete"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-date-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_date_reg" name="form[wb_date_reg]" type="text" value="2020-06-08 09:41:40"><span></span>
</div>
</div>
</div>
</div>
</div>
I am trying to create a form in a NgbModal, I can open an initialize the form however when I press submit button, nothing happens.
Here is HTML code;
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Give your feedback</h4>
</div>
<form [formGroup]="addForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="form-group">
<label>Title</label>
<input type="text" formControlName="title" class="form-control" [ngClass]="{ 'is-invalid': submitted && addForm.controls.title.errors }" />
<div *ngIf="submitted && addForm.controls.title.errors" class="invalid-feedback">
<div *ngIf=" addForm.controls.title.errors">* Title is required</div>
</div>
</div>
<div class="form-group">
<label>Comment</label>
<textarea type="text" rows="4" cols="50" formControlName="text" class="form-control" [ngClass]="{ 'is-invalid': submitted && addForm.controls.text.errors }"></textarea>
<div *ngIf="submitted && addForm.controls.text.errors" class="invalid-feedback">
<div *ngIf=" addForm.controls.text.errors">* Comment is required</div>
</div>
</div>
<div class="form-group">
<label>Rate</label><br>
<ngb-rating formControlName="rate" max="5" [starTemplate]="rate">
</ngb-rating>
</div>
</div>
<div class="modal-footer">
<button style="margin-left: 5px" type="submit" class="btn btn-success pull-right">Save</button>
<button type="button" class="btn btn-outline-danger pull-right" (click)="c('cancelled')">Cancel</button>
</div>
</form>
</ng-template>
<ng-template #rate let-fill="fill" let-index="index">
<span class="star" [class.filled]="fill === 100">★</span>
</ng-template>
<ng-template #rate let-fill="fill" let-index="index">
<span class="star" [class.filled]="fill === 100">★</span>
</ng-template>
<button *ngIf="authService.currentUserValue" type="button" style="height: 50px" (click)="open(content)" class="btn btn-outline-primary pull-right" data-toggle="modal">
give your feedback
</button>
My open button works fine and also I can close modal, but somehow save is not working. Additionally my onSubmit method is like;
onSubmit() {
this.submitted = true;
const data = {
productId:this.currentProduct.productId,
userId: this.authService.currentUserValue.userId,
title: this.addForm.controls.title.value,
text: this.addForm.controls.text.value,
rating: this.addForm.controls.rating.value,
};
this.loading = true;
this.commentService.addComment(data).subscribe(
data => {
this.success = true;
this.router.navigate(['/']);
},
error => {
this.error = error;
this.loading = false;
}
)
}
No error is thrown or no action happens, clicking is not working. How can I fix this?
Your component doesn't know which modal to close. You need to pass the NgbModal reference to the submission function.
<form [formGroup]="addForm" (ngSubmit)="onSubmit(content)">
'content' refers to the template reference of the modal.
onSubmit(modal: NgbModal) {
modal.dismiss(); // Add wherever you need
}
And just as a heads up, if you...
<form [formGroup]="addForm" (ngSubmit)="onSubmit()" #f="ngForm"> /* Last attribute added */
and then create add a ViewChild before the constructor...
#ViewChild('f') ngForm: NgForm;
you'll be able to access ngForm's submission status by this.ngForm.submitted rather then setting them yourself manually. Angular docs for NgForm
I have made a form group where the purpose is to register cars.
On submit it is generating a JSON from the values inserted.
The issue is that the value from the dropdown menu is not present in the JSON.
The dropdown menu is populated with the choices shown below and is the first entry in the form group.
The label names and error messages are in Norwegian but the essence should be there.
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-3 col-sm-12 offset-md-4">
<h3>Fyll inn</h3>
<form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
<div class="form-group">
<label for="CarType">Bil type</label>
<select id="CarType" name="CarType" [(ngModel)]="CarType" class="form-control">
<option [ngValue]="CarType" *ngFor="let CarType of CarTypes" [value]="CarType.Id">{{CarType.Name}}</option>
</select>
</div>
<div class="form-group">
<label for="LicensePlate">Skiltnummer</label>
<input type="text" class="form-control" name="LicensePlate" [(ngModel)]="model.LicensePlate" #LicensePlate="ngModel" [ngClass]="{ 'is-invalid': f.submitted && LicensePlate.invalid }" required />
<div *ngIf="f.submitted && LicensePlate.invalid" class="invalid-feedback">
<div *ngIf="LicensePlate.errors.required">Skiltnummer er påkrevd</div>
</div>
</div>
<div class="form-group">
<label for="KilometersDriven">Kilometerstand</label>
<input type="number" class="form-control" name="KilometersDriven" [(ngModel)]="model.KilometersDriven" #KilometersDriven="ngModel" [ngClass]="{ 'is-invalid': f.submitted && KilometersDriven.invalid }" required />
<div *ngIf="f.submitted && KilometersDriven.invalid" class="invalid-feedback">
<div *ngIf="KilometersDriven.errors.required">Kilometerstand er påkrevd</div>
</div>
</div>
<div class="form-group">
<label for="Seats">Antall seter</label>
<input type="number" class="form-control" name="Seats" [(ngModel)]="model.Seats" #Seats="ngModel" [ngClass]="{ 'is-invalid': f.submitted && Seats.invalid }" required />
<div *ngIf="f.submitted && Seats.invalid" class="invalid-feedback">
<div *ngIf="Seats.errors.required">Antall seter er påkrevd</div>
</div>
</div>
<div class="form-group">
<label for="Gears">Antall gir</label>
<input type="number" class="form-control" name="Gears" [(ngModel)]="model.Gears" #Gears="ngModel" [ngClass]="{ 'is-invalid': f.submitted && Gears.invalid }" required />
<div *ngIf="f.submitted && Gears.invalid" class="invalid-feedback">
<div *ngIf="Gears.errors.required">Antall gir er påkrevd</div>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary">Registrer</button>
</div>
</form>
</div>
</div>
</div>
</div>
import { Component, OnInit } from '#angular/core';
import { CarType } from 'src/shared/models/cartype.model';
#Component({
selector: 'app-add-car',
templateUrl: './add-car.component.html',
styleUrls: ['./add-car.component.css']
})
export class AddCarComponent implements OnInit {
CarTypes: CarType[] = [
{ Id: 1, Name: 'SUV' },
{ Id: 2, Name: 'Coupe' },
{ Id: 3, Name: 'Sedan' }
]
model: any = {};
onSubmit() {
console.log(this.model)
alert('SUCCESS \n\n' + JSON.stringify(this.model))
}
constructor() { }
ngOnInit() {
}
}
export class CarType {
Id: number;
Name: String;
}
To the right is a link to the fill in form on the website.
To the right is a image of the JSON reply created from the previous picture
{LicensePlate: "RH123123", KilometersDriven: 120000, Seats: 5, Gears: 6}
You didn't bind it with the model object [(ngModel)]="CarType"
<select id="CarType" name="CarType" [(ngModel)]="model.carType" class="form-control">
<option [ngValue]="CarType" *ngFor="let CarType of CarTypes" [value]="CarType.Id">{{CarType.Name}}</option>
</select>
i'm using Angular, express (node).
I am opening a modal after validating the user's data at login (httpClient - express).
But when I open the modal (yes, the modal opens) I get an exception in the console:
ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked. Previous value:
'ng-untouched: true'. Current value: 'ng-untouched: false'.
Here is my basic code:
example.html
<ng-template #modalexample let-c="close" let-d="dismiss">
/** modal body **/
</ng-template>
form (ngSubmit)="f.form.valid && signin()" #f="ngForm" class="m-login__form m-form" action="">
<ng-template #alertSignin></ng-template>
<div class="form-group m-form__group">
<input class="form-control m-input" type="text" placeholder="Email" name="email" [(ngModel)]="model.email" #email="ngModel" autocomplete="off">
</div>
<div class="form-group m-form__group">
<input class="form-control m-input m-login__form-input--last" type="password" placeholder="Password" name="password" [(ngModel)]="model.password" #password="ngModel">
</div>
<div class="row m-login__form-sub">
<div class="col m--align-left">
<label class="m-checkbox m-checkbox--focus">
<input type="checkbox" name="remember" [(ngModel)]="model.remember" #remember="ngModel">
Remember me
<span></span>
</label>
</div>
<div class="col m--align-right">
<a href="javascript:;" id="m_login_forget_password" class="m-link">
Forget Password ?
</a>
</div>
</div>
<div class="m-login__form-action">
<button [disabled]="loading" [ngClass]="{'m-loader m-loader--right m-loader--light': loading}" id="m_login_signin_submit" class="btn btn-focus m-btn m-btn--pill m-btn--custom m-btn--air">
Sign In
</button>
</div>
</form>
And my component.ts
#ViewChild('modalexample', {read: TemplateRef}) modal: TemplateRef<any>;
signin() {
console.log("Signin")
this.modalService.open(this.content);
this.loading=true;
this._authUser.login(this.model.email, this.model.password).subscribe(
response=>{
if(!response.error){
this.loading=false;
}
else{
alert('Error');
}
this.loading=false;
},
error=>{
console.log(error)
this.loading=false;
}
)
}
How can I solve it?
Thank you :D
I´m trying to apply Firebase to the Admin HTML template that I found yesterday.
In the register page when I click on Sign in it reload the page instead of do the Firebase createUserWithEmailAndPass process.
This is my HTML code:
<form [formGroup]="form" (submit)="registrar(form.value)" class="form-horizontal">
<div class="form-group row" [ngClass]="{'has-error': (!name.valid && name.touched), 'has-success': (name.valid && name.touched)}">
<label for="inputName3" class="col-sm-2 control-label">Nombre</label>
<div class="col-sm-10">
<input [formControl]="name" type="text" class="form-control" id="inputName3" placeholder="Nombre completo">
</div>
</div>
<div class="form-group row" [ngClass]="{'has-error': (!email.valid && email.touched), 'has-success': (email.valid && email.touched)}">
<label for="inputEmail3" class="col-sm-2 control-label">NIF</label>
<div class="col-sm-10">
<input [formControl]="email" type="text" class="form-control" id="inputEmail3" placeholder="NIF/DNI">
</div>
</div>
<div class="form-group row" [ngClass]="{'has-error': (!password.valid && password.touched), 'has-success': (password.valid && password.touched)}">
<label for="inputPassword3" class="col-sm-2 control-label">Contraseña</label>
<div class="col-sm-10">
<input [formControl]="password" type="password" class="form-control" id="inputPassword3" placeholder="Introduce una contraseña">
</div>
</div>
<div class="form-group row" [ngClass]="{'has-error': (!repeatPassword.valid && repeatPassword.touched), 'has-success': (repeatPassword.valid && repeatPassword.touched)}">
<label for="inputPassword4" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<input [formControl]="repeatPassword" type="password" class="form-control" id="inputPassword4" placeholder="Repite la contraseña">
<span *ngIf="!passwords.valid && (password.touched || repeatPassword.touched)" class="help-block sub-little-text">Las contraseñas no coinciden.</span>
</div>
</div>
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button [disabled]="!form.valid" type="submit" class="btn btn-default btn-auth">Confirmar registro</button>
</div>
</div>
</form>
And this my functions:
nuevoUsuario(email, password) {
console.log(email);
return this.af.auth.createUser({
email: email,
password: password
});
}
public registrar(datos: Object): void {
this.submitted = true;
if (this.form.valid) {
// your code goes here
const formarCorreo = this.email.value +' #maimona.com';
console.log(formarCorreo);
this.afService.nuevoUsuario(formarCorreo.toLowerCase,
this.password).then((user) => {
this.afService.saveUserInfoFromForm(formarCorreo.toLowerCase,
this.name, this.email).then(() => {
// this.router.navigate(['login']);
})
.catch((error) => {
this.error = error;
console.log(error);
});
})
.catch((error) => {
this.error = error;
console.log(error);
});
}
}
I don´t know why when I press "Confirmar registro" it reload the page instead of do the function. Well it enter the function until
console.log(formarCorreo);
You can change the type of the button to button from submit and add the function to the buttons click
<button [disabled]="!form.valid" class="btn btn-default btn-auth"
type="button" <-- type
(click)="registrar(form.value)" <--click
>Confirmar registro</button>
type="submit will make elements to reload the form
By default, html <form> elements navigate to their target attribute.
To override this (since this is what you'll want most of the time in a single-page app), angular provides the (ngSubmit) convenience event (which uses event.preventDefault(), which would solve your case anyway, but is cleanear)
<button type="submit"> is doing HTTP request to the server. It's the same like <input type="submit">.
You can change it to ordinary <button> or prevent the submitting a form using events.