How to extend the native input element in angular? - html

I am using the native input elemnt with datalist.
And I want it always select the first item as possible after every typing of filtering list.
How can I extend it as a custom compnent and edit this selection part?
Here is the html code:
<ng-container matColumnDef="productNo">
<th mat-header-cell *matHeaderCellDef class="w-150">Product No.</th>
<td mat-cell *matCellDef="let el;let i=index;"[formGroupName]="i">
<input formControlName="productNo" list="products" placeholder="...">
<datalist id="products">
<option *ngFor="let el of products;" value={{el.productNo}}> {{el.name}}</option>
</datalist>
</td>
</ng-container>

try the [selected]="item && i == 0" so if you have a angular matlistoption it gonna be like this
<mat-list-option *ngFor="let item of items, let i = index" [selected]="item && i == 0">
</mat-list-option>

Related

How to bind a text input that's inside a dynamic table?

I have a table where a column is a text input.
When the user edits the text both a save and cancel button became enabled.
The save button should just send the new value to the server. I can do that one no problem.
But the cancel button I can't figure out how to change the input back. Because with both model or a child element how do I know which element of the table I'm writing in?
The template part:
<table mat-table [dataSource]="gsServersDataSource" class="mat-elevation-z8">
<tr mat-header-row *matHeaderRowDef="gsServersHeaders"></tr>
<tr mat-row *matRowDef="let row; columns: gsServersHeaders;"></tr>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef > Name </th>
<td mat-cell *matCellDef="let element" > {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by value"> Value </th>
<td mat-cell *matCellDef="let element">
<input id="valueInput" type="text" value="{{element.value}}" (keyup)="onChangeValue()">
</td>
</ng-container>
<ng-container matColumnDef="modify">
<th mat-header-cell *matHeaderCellDef> Modify </th>
<td mat-cell *matCellDef="let element">
<button id="saveChanges" mat-mini-fab color="primary" (click)="onClickSave()" [disabled]="disabled">
<mat-icon>✓</mat-icon>
</button>
<button id="cancelChanges" mat-mini-fab color="primary" (click)="onClickCancel(element)" [disabled]="disabled">
<mat-icon>X</mat-icon>
</button>
</td>
</ng-container>
</table>
The component part:
gsServersDataSource = [{name: 'name1', value: 'value1'}];
gsServersHeaders: string[] = ['name', 'value', 'modify'];
disabled=true;
onChangeValue(){
this.disabled=false;
}
onClickSave(element: InstanceDataPoint){
//service call with new value
this.disabled=true;
}
onClickCancel(element: InstanceDataPoint){
//Put original back : How to??
this.disabled=true;
}
}
I created another value for each line that contains the temporary value the user inputted.
When the user wants to save it, it will be posted and on success saved as the original value.
When the user wants to cancel the changes. The temporary value will be reset to the original value.
On the template I'm now using the newValue as the value of the text input.
And I'm passing to the keyup hook the inputted value
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by value"> Value </th>
<td mat-cell *matCellDef="let element">
<input id="valueInput" type="text" value="{{element.newValue}}" (keyup)="onChangeValue(element,$event.target.value)">
</td>
</ng-container>
On the component, I'm now saving the inputted value to the newValue on changes to the text input.
On clicking save I'm assigning the newValue to the originalValue if the post is successful.
And on clicking cancel I'm putting the newValue back to the originalValue.
onChangeValue(element: InstanceDataPoint, newValue: string){
element.disabled = false;
element.newValue = newValue;
}
onClickSave(element: InstanceDataPoint){
this.gsInstancesService.postModifiedValue(this.selectedEnvironment,
{ "param-name": element.name, "param-val": element.newValue, "server-id": element.server, "language": element.language}).
subscribe({complete: ()=>element.value=element.newValue});
element.disabled=true;
}
onClickCancel(element: InstanceDataPoint){
element.newValue = element.value;
element.disabled = true;
}

Angular Material Table, multiple filters with each a column

I have build a table in Angular Material with a general filter (I have followed the official documentation for that). For the purpose of my project I would like to have different filter for each column of my table. For example a filter for the column "name" and another filter for the column "amount". How can I achieve this?
html
<mat-form-field appearance="standard" color="accent">
<mat-label>Filter</mat-label>
<input matInput (keyup)="applyFilter($event)" placeholder="Search" #input>
</mat-form-field>
<table mat-table [dataSource]="expense" class="mat-elevation-z8">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let element"> {{element.amount | currency:'CHF '}} </td>
</ng-container>
[...]
</table>
typescript
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}

Column not showing - mat-table

I am attempting to add row-deletion into my <mat-table>. Most of the table is working fine, except the checkbox column is not showing up. Previously, the code did not contain the <!-- Checkbox/Selection Column --> section. I added it in using one of the examples on angular.material.io.
Im a bit confused, because it looks to me like the pattern should be a <th> & <td> wrapped inside an <ng-container>. I seem to be missing something here, because the checkbox/selection column isn't showing up, there aren't any errors in the browser console, and there aren't any errors being thrown at ng serve in powershell.
<table mat-table [dataSource]="dataSource" matSort>
<!-- Checkbox/Selection Column -->
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox [checked]="false" [aria-label]="checkboxLabel()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox [checked]="true"></mat-checkbox>
</td>
</ng-container>
<!-- Working Columns -->
<ng-container *ngFor="let field of Fields" matColumnDef="{{field.name}}">
<th class="w-134" mat-header-cell *matHeaderCellDef mat-sort-header>{{field.name}}</th>
<td class="w-130" mat-cell *matCellDef="let row">
<input *ngIf="field.editType == 'free'" matInput [(ngModel)]="row[field.name]" placeholder="{{row[field.name]}}" required>
<mat-select *ngIf="field.editType == 'spinner'" [(ngModel)]="row[field.name]">
<mat-option *ngFor="let option of field.options" [value]="option">{{option}}</mat-option>
</mat-select>
<div class="checkbox-cell" (click)="toggleBoolean(row, field.name)">
<mat-checkbox *ngIf="field.editType == 'checkbox'" [(ngModel)]="row[field.name]" (click)="toggleBoolean(row, field.name)"></mat-checkbox>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="ColumnHeaders"></tr>
<tr mat-row *matRowDef="let row; columns: ColumnHeaders;"></tr>
</table>
Seems like you did not added the column in your ColumnHeaders array inside TS file.
ColumnHeaders = ['select'] //ColumnHeaders should have an entry of select(your checkbox column defintion)
yes you have to add select inside displayedColumns
displayedColumns: string[] = ['select','position', 'name','gender', 'weight', 'symbol'];

How to position check boxes under a column header vertical in angular material?

I have a angular material table with some header column. But under one header column I have some checkboxes for the name of the project.
I have it like this:
<ng-container matColumnDef="projects">
<th mat-header-cell *matHeaderCellDef (mouseover)="show = true" (mouseout)="show = false" mat-sort-header i18n>
<div class="col">
<div class="row" *ngFor="let item of returnProjectCodes; let i = index">
<mat-checkbox
(click)="$event.stopPropagation()"
(change)="filterProjects($event, i, item)"
[checked]="selected === i"
[disabled]="isDisabled"
>{{ item.name }}
</mat-checkbox>
</div>
</div>
Project
</th>
<td mat-cell *matCellDef="let row">{{ row.projects }}</td>
</ng-container>
But now it looks like this:
But of course the header column project has to bee positioned above the checkboxes in line with the other column headers.
So what I have change?
Thank you

Disable MatSort on space key pressed Angular Material

So I'm using angular material tables and decided to made a filter for each column. The inputs for this filters are located in the row header of each column. That works fine, but the thing is when I'm typing and pressed the space key, the table gets sorted. I want this behavior to stop, but if I used (keydown.space)="$event.preventDefault()" but the space isn't inserted in the input. Here is the code below of the table.
<table mat-table class="full-width-table" (matSortChange)="sortData($event)" [dataSource]="this.datasrcCollIndex" aria-label="Elements" matSort matSortActive="strName" matSortDirection="asc" matSortDisableClear>
<!-- Name Column -->
<ng-container matColumnDef="strName">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
<mat-form-field style="margin-top: 0px;">
<input matInput placeholder="Name" (keyup)="filteringByColumns()" [(ngModel)]="strName" >
</mat-form-field>
</th>
<td mat-cell *matCellDef="let user">{{user.strName}}</td>
</ng-container>
<!-- Gender Column -->
<ng-container matColumnDef="strGender">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
<mat-form-field style="margin-top: 0px; width: 70px;">
<input matInput placeholder="Gender" (keyup)="filteringByColumns()" [(ngModel)]="strGenderColumn">
</mat-form-field>
</th>
<td mat-cell *matCellDef="let user">{{user.strGender}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="this.dictstrDisplayedColumns"></tr>
<tr mat-row (click)="this.showDetailsOfUsers(user)"
*matRowDef="let user; columns: this.dictstrDisplayedColumns;"></tr>
</table>
Instead of using
preventDefault()
I used
stopPropagation()
it still allows input to be entered, but does not propagate the event to the parent elements (thus the sorting element never receiving the event).
Usage:
(keydown.space)="$event.stopPropagation()"
i had the same problem and did:
event.preventDefault();
(event.target as any).value += ' ';