I have a search 'form' with angular material. But it is not a form with a submit button. But just a button. like this:
<button mat-raised-button color="accent" class="Button" (click)="searchFor()">Filter</button>
and I have a dropdownlist. But I want to make the dropdownlist required.
Like this:
<div class="search-select searchstatus" *ngIf="selectedSearch && hasStatusOptions(selectedSearch)">
<mat-select placeholder="Status" name="option" [(ngModel)]="selectedValue" required>
<mat-option *ngFor="let option of getStatusOptions(selectedSearch)" [value]="option.apiStatus">
{{ option.status }}
</mat-option>
</mat-select>
</div>
But his doesnt work.
So how to make the dropdownlist required? Thank you
For datepicker it works. If I do this:
<input matInput readonly required [matDatepicker]="picker1" placeholder="start datum" [(ngModel)]="startDate" />
Then if there is no date entered the label becomes red and there is showing a *
if I do this:
<mat-select #statusSelect placeholder="Status" name="option" [(ngModel)]="selectedValue" [required]="true" >
and this:
<button [disabled] = '!statusSelect.value' mat-raised-button color="accent" class="Button" (click)="searchFor()">Filter</button>
I get this error:
ExtendedSearchComponent.html:62 ERROR TypeError: Cannot read property 'value' of undefined
I am guessing from the information provided that you want to select a value from the dropdown and filter based on that. So, you can disable the filter till a value is selected in the dropdown. Maybe something like this.
<div>
<mat-select placeholder="Status" name="option" [(ngModel)]="selectedValue" required>
<mat-option></mat-option>
<mat-option *ngFor="let option of tableDef" [value]="option">
{{ option.header }}
</mat-option>
</mat-select>
</div>
<button mat-raised-button color="accent" class="Button" (click)="searchFor()" [disabled]="!selectedValue">Filter</button>
Edit:-
I saw your comments above after the edit. Instead of using the css selector (#statusSelect.value), you can directly check by the object you are binding to the [(ngModel)] i.e "selectedValue"
You seem to be pretty close. The API Section for the Select component at the Angular Material page offers a required: boolean Input. Changing:
<mat-select placeholder="Status" name="option" [(ngModel)]="selectedValue" required>
to
<mat-select placeholder="Status" name="option" [(ngModel)]="selectedValue" [required]="true">
might be what you wanted?
The most proper way is to make template-driven form.
But you can bind your dropdown to template reference variable without any form usage.
<mat-select #yourSelect></mat-select>
<button [disabled]='!yourSelect.value'>Button</button>
Related
I want to call a function, once the value of dropdown is changed.
I have done this without Angular Material.
Here's my ts and html files.
selected="pending";
getRequests(event: any) {
this.selected = event.target.value;
if(this.selected=="pending")
console.log("Inside Pending Requests")
else
console.log("Inside Granted Requests")
}
<div style="margin-left: 70%;" appearance="fill">
<select (change)="getRequests($event)">
<option value="pending">Pending</option>
<option value="granted">Granted</option>
</select>
</div>
Now, I want to implement this with the help of Angular Material Select Component.
Calling the getRequests() function is not working as expected. Somebody please help me on this one. Thanks in advance.
<mat-form-field style="margin-left: 70%;" appearance="fill">
<mat-label>Status</mat-label>
<mat-select [(value)]="selected" (change)="getRequests($event)" >
<mat-option value="pending">Pending</mat-option>
<mat-option value="granted">Granted</mat-option>
</mat-select>
The api is selectionChange i.e. (selectionChange)="getRequests($event)".
See the docs https://material.angular.io/components/select/api
In Angular Material Design 6 and above, the (change) method was removed. Instead use selectionChange
<mat-select (selectionChange)="doSomething($event)">
Read more about here: Angular 6 Material mat-select change method removed
Use selectionChange intead of change
<mat-form-field style="margin-left: 70%;" appearance="fill">
<mat-label>Status</mat-label>
<mat-select [(value)]="selected" (selectionChange)="getRequests($event)" >
<mat-option value="pending">Pending</mat-option>
<mat-option value="granted">Granted</mat-option>
</mat-select>
Then you should be able to access value from event object value property
getRequests(event: MatSelectChange) {
this.selected = event.value;
if(this.selected=="pending")
console.log("Inside Pending Requests")
else
console.log("Inside Granted Requests")
}
Working Example
your mat-select has an event that is emitted every time selection is changed. It is called selectionChange as per angular documentation: https://material.angular.io/components/select/api
so maybe try to chage your (change) to (selectionChange) like this:
<mat-form-field style="margin-left: 70%;" appearance="fill">
<mat-label>Status</mat-label>
<mat-select [(value)]="selected" (selectionChange)="getRequests($event)" >
<mat-option value="pending">Pending</mat-option>
<mat-option value="granted">Granted</mat-option>
</mat-select>
I spent a lot of time solving this problem and failed. I want to select to display the name and get the id. The problem is, as soon as a value is selected, the number (id) of that value is displayed. My code:
<mat-form-field class="example-full-width">
<input
matInput
placeholder="Search your product"
formControlName="id"
[matAutocomplete] = "auto">
<mat-autocomplete #auto="matAutocomplete" >
<mat-option *ngFor="let option of allProducts; let i = index" [value]="option.id" >
{{ option.name }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
I tried to create a function (onSelectionChange) but could not display the name and take the value as (id)
Well, you have to use the input function of auto-complete called displayWith.
you can find the solution to your problem in this link here
plus I 've made a stackblitz example for you to simplify it more.
Example
to describe the solution:
you have to add to your autocomplete component an input called displayWith
<mat-autocomplete #auto="matAutocomplete" [displayWith]="checkValue">
and then in your component you have to create the function checkValue
checkValue(value: any) {
// here you can get your id or whatever you want
console.log(value)
}
then you have to add to your mat option the value and give it your whole object as value
<mat-option *ngFor="let option of options" [value]="option" >
{{option.name}}
</mat-option>
Please check the stackblitz example for more details
I have a working slide toggle that is working perfectly except when I want to change the location for the toggle on the view to next to the form it doesn't work. Once I put it within the form tag the toggle will stop changing on click and will remain false.
I have looked at other examples but they are not using mat form field as is done in this code. I need to put the toggle next to the submit button but the mat form field seems to make it not work. Also I tried to add the same class to the form tag but that doesn't seem to work.
<div class="container w-75 example-margin">
<div class="row text-center mx-auto">
<form class="form-inline row text-center mx-auto" [formGroup]="slgForm">
<div class="form-group">
<mat-form-field class="mr-4">
<input matInput formControlName="year" placeholder="Year">
</mat-form-field>
<mat-form-field class="mr-4">
<input matInput formControlName="quarter" placeholder="Quarter">
</mat-form-field>
<mat-form-field class="mr-4">
<input matInput formControlName="week" placeholder="Week">
</mat-form-field>
<mat-form-field class="mr-4">
<mat-select [(ngModel)]="selectedDepartment" formControlName="dept">
<mat-option *ngFor="let department of departments" [value]="department">
{{department}}
</mat-option>
</mat-select>
</mat-form-field>
<button mat-raised-button (click)="submit()">Submit</button>
</div>
</form>
<div>
<mat-slide-toggle [(ngModel)]="checked"
class="example-margin"
[color]="color"
(change)="changed()">
Remove {{checked}}
</mat-slide-toggle>
</div>
</div>
</div>
[(ngModel)]="checked"
When you put the slide toggle out the form, your model is not binding to the form.
Why do you want to put it outside the form?
I have datatable which will show the elements with edit button also top of the page i have add button .
Add is for adding elements into list edit is for editing the particular row data
when user click add button one popup will come with two dropdownlist
Element Name and Element symbol
here based on Element Name selection Element symbol list will come.
My expectation >
when i click first row edit button(which means Hydrogen H ) same popup should open and we need to populate these Hydrogen(Element Name) and H(Element symbol) in dropdown like this
when i click 2nd row edit buttin (Hydrogen ,H1) it should populate these data
here is my Dialogue html
<h1 mat-dialog-title>{{data.element.ModalName.name}} </h1>
<form [formGroup]="addTaskForm" (ngSubmit)="save()" >
<mat-form-field>
<mat-select formControlName="name" placeholder="Element Name"
(selectionChange)="elementSelectionChange($event)">
<mat-option *ngFor="let element of Elements" [value]="element.name">
{{ element.name }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select formControlName="symbol" placeholder="Element symbol">
<mat-option *ngFor="let element of selectedElementSymbols" [value]="element.symbol">
{{ element.symbol }}
</mat-option>
</mat-select>
</mat-form-field>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()">Cancel</button>
<button type="submit" mat-button cdkFocusInitial>{{data.element.ModalName.button}}</button>
</div>
</form>
https://stackblitz.com/edit/angular-talrct-prnwvr
In above template I basically made two changes one on line 27 commented re initialization of element and in constructor to update list of symbols based on selection.
You need to add (click)="onEditClick()" event to HTML of your popup button. Then in TS file add onEditClick(){} and there you can catch data you have chosen in dropdowns
store the selected table value to a variable like public
selected2 = this.options2[1].id ...
and bind with mat-option
<mat-select [(ngModel)]="selected2">
<mat-option *ngFor="let option of options2" [value]="option.id">{{
option.name }}</mat-option>
</mat-select>
I have a simple form which operates on the logic of:
Select Box 1 (Yes/No)
Select Box 2 (Show if Yes)
Select Box 3 (Show if No)
Only the shown selection box should be set to required, the other is not required.
<mat-select placeholder='Show First Options' formControlName='b' [(ngModel)]="view">
<mat-option [value]="'first'">
First
</mat-option>
<mat-option [value]="'second'">
Second
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="view === 'first'">
<mat-select
placeholder='First Items'
formControlName='one'
[required]="view === 'first'">
<mat-option *ngFor="let item of items1" [value]="item">
{{item}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="view === 'second'">
<mat-select
placeholder='Second Items'
formControlName='two'
[required]="view === 'second'">
<mat-option *ngFor="let item of items2" [value]="item">
{{item}}
</mat-option>
</mat-select>
</mat-form-field>
This works fine for the first, default select box. However, when you change to the second box, the first box seems to keep its required validator.
I have written a demo to demonstrate this:
https://stackblitz.com/edit/angular-9eoffq
How can I ensure only the viewed select box is required?
Apologies for editing the demo provided as people were reviewing it which caused confusion, however I seemed to have solved it - the issue seemed to stem from the DOM re-rendering to remove the mat-form-field before removing the required tag. This meant that the form still had the required attribute.
The demo has been updated with the solution - I had to programatically remove the required validator and add it to the appropriate form control. Then I had to update the value and validity to clear the errors after the validators were changed.
this.form.valueChanges.subscribe(value => {
if(value.b === 'first') {
this.form.controls['one'].setValidators(Validators.required)
this.form.controls['two'].clearValidators()
} else {
this.form.controls['two'].setValidators(Validators.required)
this.form.controls['one'].clearValidators()
}
this.form.controls['one'].updateValueAndValidity({onlySelf:true})
this.form.controls['two'].updateValueAndValidity({onlySelf:true})
})
Instead of using ngModel you can instead make full use of your reactive form, and utilize the form controls. Also, by disabling and enabling fields they are either included/excluded from the form object, therefore also validations will not apply.
You could listen to valueChanges of form, but I like to avoid it since if you are having a large form, it will be fired excessively. But if you want to only listen to a specific control changes, you can also do that. I like a simple change event here though:
<mat-select formControlName='b' (change)="onChange()">
and then hiding/showing the other select:
<mat-form-field *ngIf="form.controls.b.value === 'first'">
<!-- -->
<mat-form-field *ngIf="form.controls.b.value === 'second'">
and the change event:
onChange() {
if(this.form.get('b').value === 'first') {
this.form.get('one').enable()
this.form.get('two').disable()
} else {
this.form.get('one').disable()
this.form.get('two').enable()
}
}
DEMO
With this, we need to remember that the disabled control(s) are excluded from the form object, if you want all values (disabled included), you need to call this.form.getRawValue()
Still some one is looking for another solution, this may help.
<mat-select placeholder='Show First Options' formControlName='b' [(ngModel)]="view" #optionsSelector>
<mat-option value="first"> First </mat-option>
<mat-option value="second"> Second </mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="optionsSelector.value === 'first'">
<mat-select placeholder='First Items' formControlName='one'>
<mat-option *ngFor="let item of items1" [value]="item">
{{item}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="optionsSelector.value === 'second'">
<mat-select placeholder='Second Items' formControlName='two'>
<mat-option *ngFor="let item of items2" [value]="item">
{{item}}
</mat-option>
</mat-select>
</mat-form-field>