Background
I have a form where I give the user the option to specify either a quick time-frame or a detailed one (with a specific start/end time) - i.e. the user has the option to fill only one out of the two
The type of option that they wish to choose can be toggled with the click of a button. These buttons just toggle the hidden parameter on the specified divs
Issue
My problem here is that both of these fields (all 3 technically as start/end time are 2 separate form group divs under one generalized div) are required only if they are not hidden - I am not sure how this can be achieved with Angular 4/5/6 (using 6 here)
My invalid form trigger always goes off as the hidden field is also required
My Form
<div class="card-block">
<form #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
<div class="form-group">
<label for="transactionType"> Request Type </label>
<select
class="form-control"
[(ngModel)]=data.transactionType
name ="transactionType"
#transactionType="ngModel"
required>
<option value="something1Count">Something1</option>
<option value="something2Count">Something2</option>
</select>
<div *ngIf="transactionType.errors?.required && transactionType.touched" class="alert alert-danger">
Please select a transaction type
</div>
</div>
<br>
<div class="form-group">
<label>Timeframe Type</label>
<br>
<button type="button" class="btn btn-light" (click)="quickTimeframe = false; detailedTimeframe = true;" ng-selected="!quickTimeFrame"> Quick </button>
<button type="button" class="btn btn-light" (click)="detailedTimeframe = false; quickTimeframe = true;" ng-selected="!detailedTimeframe"> Detailed </button>
</div>
<div class="form-group" [hidden]="quickTimeframe">
<label for="timeframe">Timeframe</label>
<select
class="form-control"
[(ngModel)]=data.timeframe
name ="timeframe"
#timeframe="ngModel"
required>
<option value="15">15 Minutes</option>
<option value="30">30 Minutes</option>
<option value="45">45 Minutes</option>
<option value="60">60 Minutes</option>
</select>
<div *ngIf=" !quickTimeframe && timeframe.errors?.required && timeframe.touched" class="alert alert-danger">
Please select a timeframe
</div>
</div>
<div class="detailed" [hidden]="detailedTimeframe">
<div class="form-group">
<label for="startTime">Start of Time Range</label>
<input
type="datetime-local"
class="form-control"
[(ngModel)]="data.startTime"
#startTime="ngModel"
name="startTime"
required
>
<div *ngIf="!detailedTimeframe && startTime.errors?.required && startTime.touched" class="alert alert-danger">
Please select a start-time
</div>
</div>
<div class="form-group">
<label for="endTime">End of Time Range</label>
<input
type="datetime-local"
class="form-control"
[(ngModel)]="data.endTime"
#endTime="ngModel"
name="endTime"
required
>
<div *ngIf="!detailedTimeframe && endTime.errors?.required && endTime.touched" class="alert alert-danger">
Please select an end-time
</div>
</div>
</div>
<input type="submit" class="btn btn-primary btn-block" value="Submit">
</form>
</div>
</div>
TS File
import { Component, OnInit } from '#angular/core';
import { Inputs } from '../../models/Inputs';
import { Router } from '#angular/router';
import {FlashMessagesService} from 'angular2-flash-messages';
#Component({
selector: 'app-main-form',
templateUrl: './main-form.component.html',
styleUrls: ['./main-form.component.css']
})
export class MainFormComponent implements OnInit {
data:Inputs = {
transactionType:'',
timeframe:null,
startTime:'',
endTime:''
};
quickTimeframe:boolean=true;
detailedTimeframe:boolean=true;
buttonResult:any;
constructor(public router:Router, public flashMessagesService:FlashMessagesService) {
}
ngOnInit() {
}
onSubmit({value, valid}:{value:Inputs, valid:boolean}){
console.log("Quick Time Flag: " +this.quickTimeframe);
console.log("Detailed Time Flag: " +this.detailedTimeframe);
if (valid && !this.quickTimeframe){
console.log("Form is valid");
//Stuff should happen
console.log(value);
} else if (valid && !this.detailedTimeframe) {
console.log(this.data.startTime);
//Other stuff should happen
}
else {
console.log("Form is not valid");
this.flashMessagesService.show('Choose Valid Parameters', {cssClass:'alert-danger', timeout: 4000});
}
}
radioClick() {
console.log(this.buttonResult);
}
}
Report Inputs Interface (for completion's sake)
export interface Inputs {
transactionType?:string;
timeframe?:number;
startTime?:string;
endTime?:string;
}
*ngIf did the trick
Using ngIf instead of hidden ensure that the elements do not exist within the form in my scenario
Related
I am trying to pass the html elements of a form through the submit function as parameters. I can get correctly the nameInput element with flag #nameInput, but the select element (#skillSelect) is throwing this error:
- error TS2339: Property 'skillSelect' does not exist on type 'MemberFilterComponent'.
Here is my form template. How can I pass the select element to component as I did with the input text?:
<form
[formGroup]="filterMemberForm"
(ngSubmit)="onSubmit(nameInput, skillSelect)"
>
<div class="form-row">
<div class="col-md-3">
<label class="font-weight-bold"
>Name
<input
ngDefaultControl
type="text"
class="form-control"
label="'Name'"
formControlName="name"
placeholder=" Ex: Maria Novillo"
required
id="name"
#nameInput
(change)="mapChipValue(nameInput)"
/></label>
</div>
<div class="col-md-3" *ngIf="skills.length !== 0">
<label class="font-weight-bold">Skills:</label>
<select
id="skillId"
class="form-control"
formControlName="skillId"
#skillSelect
(change)="mapChipValue(skillSelect)"
>
<option value="">-- Select skills --</option>
<option *ngFor="let skill of skills" [value]="skill.idSkill">
{{ skill.skill }}
</option>
</select>
</div>
<div class="form-row">
<div class="col-md-3 mt-5">
<button type="submit" class="btn btn-primary">Apply</button>
</div>
</div>
</form>
In the html file:
<select class='select-option'
#mySelect
(change)='onOptionsSelected(mySelect.value)'>
<option class='option'
*ngFor='let option of dropDownData'
[value]="option.seo_val">{{option.text_val}}</option>
</select>
In the ts file:
onOptionsSelected(value:string){
console.log("the selected value is " + value);
}
why you need pass the "html element"? in filterMemberForm.value you has an object with the values. Really your form should be
<form
[formGroup]="filterMemberForm"
(ngSubmit)="onSubmit(filterMemberForm)"
>
onSubmit(form:FromGroup)
{
if (form.valid)
console.log(form.value)
else
form.markAllAsTouched()
}
if you need the selectOption name always can makes
onSubmit(form:FromGroup)
{
if (form.valid)
{
//if is not multiple select
const selectedItem=this.skills.find(x=>x.idSkill==form.value.skillId)
console.log(form.value,selectedItem)
//if is multiple select
const selectedItems=this.skills.filter(
x=>form.value.skillId.indexOf(x.idSkill)>=0)
console.log(form.value,selectedItems)
}
else
form.markAllAsTouched()
}
but I got this error,
Object is possibly 'null
<span *ngIf="name.errors.minlength">You must enter atleast 3 characters
why my error object is always null,minlength is not store in my error object what is the reason for that?
My hero.ts file is,
export class Hero {
constructor(
public id: number,
public name: string,
public email: string
) { }
}
My formone.component.ts file is,
import { Component, OnInit } from '#angular/core';
import {NgForm} from "#angular/forms";
import {Hero} from "../../hero"
#Component({
selector: 'app-formone',
templateUrl: './formone.component.html',
styleUrls: ['./formone.component.css']
})
export class FormoneComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
model = new Hero(1, 'chamara','chamara#gmail.com');
submitted = false;
onSubmit() { this.submitted = true; }
get diagnostic() { return JSON.stringify(this.model); }
}
My formone.component.html file is,
<div class="container mt-3">
<div class="row">
<div class="col-md-2">
</div>
<div class="col-md-8">
<h4>Template Driven Forms</h4>
<form #formone="ngForm" (ngSubmit)="onSubmit()">
{{diagnostic}}
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name"
required
[(ngModel)]="model.name" name="name" #name="ngModel" minlength="3" #x>
</div>
<div *ngIf="!name.valid" class="alert alert-danger" >
<span *ngIf="name.errors.minlength">You must enter atleast 3 characters</span>
<span *ngIf="name.errors.required">This field required</span>
</div>
<div class="form-group">
<label for="alterEgo">Email</label>
<input type="email" class="form-control" id="alterEgo"
[(ngModel)]="model.email" name="alterEgo">
</div>
<br>
<button type="submit" class="btn btn-primary" [disabled]="!formone.form.valid">Submit</button>
</form>
</div>
<div class="col-md-2">
</div>
</div>
</div>
Plz help me to fix this,
Your Approach seems to be fine (at least for me), might you need to take care of few things
Remove extra #X from input code (this is causing issue by misleading error checking) and try to add name?.errors?.minlength just cross check name exists while checking errors.
<input type="text" class="form-control" id="name" required
[(ngModel)]="model.name" name="name" #name="ngModel" minlength="3">
<span *ngIf="name?.errors?.minlength">You must enter atleast 3 characters</span>
You can check more about template driven error handling here:
https://medium.com/swlh/form-validation-with-angular-template-driven-forms-8e0756cbec5
Happy Coding.. :)
I have an angular form (not reactive).It has some required fields which get highlighted in red if empty during submission of the form. Now if I submit the form and then empty the required fields, still the fields get highlighted(even though the form is not submitted again) . Is there a way to not show this validation until the form is submitted again?
<form name="form" (ngSubmit)="f.form.valid && moveAsset()" #f="ngForm" novalidate>
<button type="submit" id="MoveAsset" name="MoveAsset" tabindex="214"
class="btn btn-primary pull-right" data-dismiss="modal"
[disabled]="assetMoveFieldAccessData['Move']">
{{fields['Move']}}
</button>
<div class="form-group required">
<label class="col-form-label control-label col-sm-4 for="site">
{{fields['Site']}}
</label>
<ng-select ngSelectSetTabindex [items]="siteList" name="siteid" id="siteid" tabindex="204"
(change)="siteChange()" bindLabel="siteName" bindValue="siteId" [(ngModel)]="site"
#siteid="ngModel" required placeholder="{{fields['Select Site']}}"
[ngClass]="{ 'invalid-errors-br': (f.submitted && (site == 0|| site == null || site ==
undefined))}" >
</ng-select>
</div>
</form>
Component:
myform: FormGroup;
#ViewChild('f', {static: true}) myForm;
public moveAsset(){
this.myForm.reset();
}
I am new to Angular 2. So, I have this form where I created with Angular 2, and bootstrap. So, when you click on the text field and move the mouse else where, the box turns red (which is good). But, when they click on submit button, it when the form is empty, it won't show the "required" dialog. So, please check my code of what I did wrong. Thank you!
I want to show this when they click on a empty form:
Here is the code.
<div class="col-md-8 col-md-offset-2">
<form (ngSubmit)="onSubmit(form)" #form="ngForm">
<div class="form-group">
<label for="content">Content</label>
<input type="text"
id="content"
class="form-control"
ngModel
name="content"
required>
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</div>
Second Part:(TypeScript)
import { Component } from "#angular/core";
import {MessageService} from "./message.service";
import {Message} from "./message.model";
import {NgForm} from "#angular/forms";
#Component({
selector: 'app-message-input',
templateUrl: './message-input.component.html'
})
export class MessageInputComponent {
constructor(private messageService: MessageService) {}
onSubmit(form: NgForm) {
const message = new Message(form.value.content, 'John');
this.messageService.addMessage(message);
form.resetForm();
}
}
I fixed my answer by enabling the default HTML validation. Becuase for some reason in Angular, the default HTML validation is disabled by Angular. So, I enabled it by doing:
<div class="col-md-8 col-md-offset-2">
<form ngNativeValidate (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group">
<label for="content">Content</label>
<input
type="text"
id="content"
class="form-control"
ngModel
name="content"
required>
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
I just add ngNativeValidate in my form tags.
i have tried with many ways:
Validation for select field angular 2
How to apply required validation to dropdown in angular 2
This help me to add validation in dropdown. but i have a issue that validation run properly but when i click on submit button it submit the form if dropdown value is valid or not. i do not want to submit my form if the value of dropdown is "select".
this is my HTML code:
<form name="form" (ngSubmit)="f.form.valid && SaveSymbol()" #f="ngForm" novalidate>
<div class="form-group" [ngClass]="{ 'has-error': f.submitted && !DisplayGroupID.valid && !manageSymbolViewModel.DisplayGroupID }">
<label for="DisplayGroupID">Display Group</label>
<select class="form-control" name="manageSymbolViewModel.DisplayGroupID" #DisplayGroupID id="manageSymbolViewModel.DisplayGroupID" [(ngModel)]="manageSymbolViewModel.DisplayGroupID" required>
<option value="0" selected disabled>Select</option>
<option *ngFor="let group of result.DisplayGroups" value={{group.DisplayGroupId}}>
{{group.DisplayGroup}}
</option>
</select>
<div *ngIf="f.submitted && !DisplayGroupID.valid && !manageSymbolViewModel.DisplayGroupID" class="help-block">Display Group is required</div>
</div>
<div class="form-group">
<button [disabled]="loading" type="submit" class="btn btn primary">Save</button>
<a [routerLink]="['/login']" class="btn btn-link">Cancel</a>
</div>
</form>
This is component code:
SaveSymbol() {
this.manageSymbolService.Save(this.manageSymbolViewModel).subscribe(data => {
debugger;
},
error => {
// this.alertService.error(error);
// this.loading = false;
});
}
}
The first and selected option of your select element has a value 0. So it basically it already has a value set to it on page load.
Try to change it to: <option value="" selected disabled>Select</option> and see if that fixes your problem.
Try this
<button [disabled]="loading || !DisplayGroupID.valid || !manageSymbolViewModel.DisplayGroupID" type="submit" class="btn btn primary">Save</button>
This will prevent the form from submitting while there is nothing selected in the dropdown or when the dropdown model is invalid.
please change your form as given below and also pass your status of form through submit function if required
<form #f="ngForm" (submit)="f.valid && SaveSymbol(f.value, f.valid)" novalidate>
<div class="form-group">
<label>Display Group</label>
<select ngControl="DisplayGroupID" #DisplayGroupID="ngForm" [(ngModel)]="manageSymbolViewModel.DisplayGroupID" required>
<option value='' disabled>Select</option>
<option *ngFor="let group of DisplayGroups" value={{group.DisplayGroupId}}>{{group.DisplayGroup}}</option>
</select>
<small [hidden]="DisplayGroupID.valid || (DisplayGroupID.pristine && !submitted)" class="text-danger">
Displaygroup is required
</small>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
and initialise the model as
this.manageSymbolViewModel = {
DisplayGroupID: ''
};
refer this plunkr http://plnkr.co/edit/sFTM22xbZSXBLZcv90o2
If I'm reading your question right...
Your first value will be 0. So simply set your [disabled] attribute accordingly.
Example: [disabled]="loading || DisplayGroupId.value == 0"
Your button will not be enabled while the first option is selected. Simple solution.