I have this HTML:
<ng-container *ngFor="let something of things; let i = index">
<span data-e2e="{{"abc" + i}}" class="checkmark"></span>
</ng-container>
I want to have this result rendered in the DOM:
<span data-e2e="abc0" class="checkmark"></span>
<span data-e2e="abc1" class="checkmark"></span>
...
But this {{"abc" + i}} wont work.
"abc" should be a string.
How can I do this, without saving the property (counter: i) to the components controller
You should change,
<ng-container *ngFor="let something of things; let i = index">
<span data-e2e="{{"abc" + i}}" class="checkmark"></span>
</ng-container>
To:
<ng-container *ngFor="let something of things; let i = index">
<span [attr.data-e2e]="'abc'+i" class="checkmark"> {{something}} </span>
</ng-container>
Here you should use attr as prefix and need to assign the value to custom attribute using property binding like, [attr.data-e2e]="'abc'+i"..
Working Stackblitz..
You should change:
<span data="normalString{{i}}" class="checkmark"></span>
normalString should be outside {{}}
also data attribute is not correct, read more how to properly add custom data attribute:
https://www.w3schools.com/tags/att_global_data.asp
Related
I have an array of input elements with formControl Directive. I have set the value of each element with value attribute, but it showing blank. If I set the value in ts file, the same value will be set in each and every element. So, how to differentiate the elements if I have to set value in ts?
Here is my code:
HTML code:
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>Amount
<button mat-icon-button (click)="onEditClick(datasource.data)">
<mat-icon style="cursor: pointer;" class="ml-2 mr-2" >edit</mat-icon>
</button>
</th>
<td mat-cell *matCellDef="let row; let i=index;">
<ng-container *ngIf="isActual">{{row.amount || "-- --"}}</ng-container>
<mat-form-field *ngIf="isEditMonth" class="example-full-width month-textbox" appearance="outline">
<input #elRef matInput type="text" [formControl]="amountField" (change)="onAmountChanged($event,row)" [value]="row.amount">
</mat-form-field>
</td>
</ng-container>
TS Code:
amountField = new FormControl();
this.form.controls['amountField'].setValue("Value you want to be selected");
You can set the value by using this.
The default value of the select element can be set by using the selected attribute on the required option. This is a boolean attribute meaning if the selected attribute is present the element will be displayed by default on the dropdown list.
I wrapped an ngx-datatable component in a form tag so I can validate inputs in the table cells. Due to the nature of how the table is populated I set the inputs name properties dynamically
<form #tableForm="ngForm">
<ngx-datatable
[rows]="_rows">
<ng-container *ngFor="let column of rowDeffinition; let columnIndex=index">
<ngx-datatable-column [prop]="column.key" [name]="column.label">
<ng-template ngx-datatable-cell-template let-rowIndex="rowIndex" let-value="value" let-row="row">
<input
class="cell-input"
(blur)="updateCellValue($event, column.key, rowIndex)"
type="text"
[ngModel]="value"
[name]="rowIndex + '-' + column.key"
/>
...
</ng-template>
</ngx-datatable-column>
</ng-container>
</ngx-datatable>
</form>
Normally, the name property would creates a local variable in the template and you can access the inputs control properties via the variable name.
<input type="text" name="name" [(ngModel)]="name" required minlength="4" />
<div *ngIf="name.invalid && name.touched">
I wonder how can I do this dynamically in the same manner I set the inputs name. So far I was able to access the input controls via the form reference but this becomes quite wordy
<span *ngIf="!tableForm.controls[rowIndex + '-' + column.key]?.valid &&
!tableForm.controls[rowIndex + '-' + column.key]?.pristine"
class="[ c-validation-message ]">
required
</span>
You can wrap your input in new component and you can access these generated components via #ViewChildren(...) in parent components .ts file:
#ViewChildren(NgxDatatableInput) datatableInputs: QueryList<NgxDatatableInput>;
I recommend to create method in parent component, which retrieves concrete datatableInput from datatableInputs by name as parameter. After that you can use this method in generated, new ValidationSpanComponent:
<ValidationSpan [control]="getDatatableInput(dynamicName)">
</ValidationSpan>
Template of ValidationSpanComponent:
<span *ngIf="!control.valid &&
!control.pristine"
class="[ c-validation-message ]">
required
</span>
Inspired by this answer I came up with following solution
<form #tableForm="ngForm">
<ngx-datatable
[rows]="_rows">
<ng-container *ngFor="let column of rowDeffinition; let columnIndex=index">
<ngx-datatable-column [prop]="column.key" [name]="column.label">
<ng-template ngx-datatable-cell-template let-rowIndex="rowIndex" let-value="value" let-row="row">
<!-- Helper template allowing to define few variables for more readable property binding-->
<ng-template #cellContent [ngTemplateOutlet]="cellContent"
let-cellName="cellName" let-isValidInput="isValidInput" let-isPristineInput="isPristineInput"
let-isRequiredInput="isRequiredInput"
[ngTemplateOutletContext]="{
cellName: rowIndex + '-' + column.key,
isValidInput: tableForm.controls[rowIndex + '-' + column.key]?.valid,
isPristineInput: tableForm.controls[rowIndex + '-' + column.key]?.pristine,
isRequiredInput: column.input?.required
}">
<input
class="cell-input"
(blur)="updateCellValue($event, column.key, rowIndex)"
type="text"
[ngModel]="value"
[name]="cellname"
/>
...
</ng-template>
</ng-template>
</ngx-datatable-column>
</ng-container>
</ngx-datatable>
</form>
This improves the general readability vastly, since my table has a very complex logic, and i track the state of the cell in a structure like:
interface EditTableRowStatus {
editing: { [coolumnId: string]: boolean},
changed: { [coolumnId: string]: boolean},
addedRow: boolean;
}
let rowsStates = EditTableRowStatus[]
which led to super complex property binding in the template
<input
class="cell-input"
*ngIf="column.input?.type === INPUT_TYPES.TEXT && (rowsStates[rowIndex]?.editing?.[column.key] || rowsStates[rowIndex]?.addedRow)"
[autofocus]="!rowsStates[rowIndex]?.addedRow || columnIndex === 0 "
(blur)="updateCellValue($event, column.key, rowIndex)"
type="text"
[ngModel]="value"
[ngClass]="{'has-changes': rowsStates[rowIndex]?.changed?.[column.key]}"
[name]="rowIndex + '-' + column.key"
[required]="column.input?.required"
/>
now becoming much more readable
<input
class="cell-input"
*ngIf="inputType === INPUT_TYPES.TEXT && (isEditing || isAddedRow)"
[autofocus]="!isAddedRow || columnIndex === 0 "
(blur)="updateCellValue($event, column.key, rowIndex)"
type="text"
[ngModel]="value"
[ngClass]="{'has-changes': isChanged}"
[name]="cellName"
[required]="isRequiredInput"
/>
I'm building up a Frontend with JSON Data.
I have to go trough a lot of arrays to check if a value exists inside. If the Value doesn't exist, then my complete HTML shouldn't render.
<ng-container *ngIf="document161['_source']['161_Events']">
<div class="row">
<span class="col-md-auto meta-object text-muted"><span>Begräbnistag:</span></span>
<span class="col">
<span *ngFor="let event of document161['_source']['161_Events']">
<span *ngFor="let sub of event.peventsub">
<ng-container *ngIf="sub.content === 'Begräbnis'">
<span *ngFor="let geburtsort of event.pstdatetypesub">
{{geburtsort.content}}
</span>
</ng-container>
</span>
</span>
</span>
</div>
<mat-divider class="my-2"></mat-divider>
</ng-container>
What i have already tried is:
<ng-template #thenBlock>
<ng-container *ngIf="document161['_source']['161_Events']">
<div class="row">
<span class="col-md-auto meta-object text-muted"><span>Begräbnistag:</span></span>
<span class="col">
<span *ngFor="let event of document161['_source']['161_Events']">
<span *ngFor="let sub of event.peventsub">
<ng-container *ngIf="sub.content === 'Begräbnis'">
<span *ngFor="let geburtsort of event.pstdatetypesub">
<ng-container ngIf="*ngIf="geburtsort.content; then thenBlock else elseBlock">
{{geburtsort.content}}
</ng-container>
</span>
</ng-container>
</span>
</span>
</span>
</div>
<mat-divider class="my-2"></mat-divider>
</ng-container>
</ng-template>
<ng-template #elseBlock>
</ng-template>
But as you can see there are multiple problems. Maybe Ii can't reach the ngIf condition if the value doesn't exist. And the then else logic doesn't work inside a ng-container template.
What should be the best solution?
try this
*ngIf="document161?._source?.161_Events?.length > 0"
If array having values it will show that element else will hide same.
I have this carousel. Each item in the carousel has a checkbox above it. I want to be able to click on item and the checkbox gets a checked attribute. The code does this. The only problem I'm having is it toggles all check boxes in the carousel. I just want it to toggle the one clicked.
<tshq-carousel [dataSource]="brands" [selections]="selectedBrands" (select)="onItemsSelected($event)" [changeKey]="changeKey" [pageSize]="5" [circular]="false"
[enableSelection]="true" mode="single">
<ng-template let-brand>
<ng-container [ngSwitch]="brand.icon&&brand.icon.length>0">
<ng-container *ngSwitchCase="true" >
<label class="apply carousel-checkbox">
<input type="checkbox" id="brandCheck" [checked]="isChecked" value="no" name = "brand">
</label>
<img [src]="formatLogo(brand.icon)" style="max-width:150px" (click)="isChecked = !isChecked" />
</ng-container>
</ng-container>
</ng-template>
</tshq-carousel>
You use isChecked variable to binding to all input checkbox of carousel, so when you change value (check or uncheck) 1 input checkbox, it also set to all remain ones.
I suggest you add 1 property to model brand and use it to binding to input checkbox or image.
Ex:
<tshq-carousel [dataSource]="brands" [selections]="selectedBrands" (select)="onItemsSelected($event)" [changeKey]="changeKey" [pageSize]="5" [circular]="false"
[enableSelection]="true" mode="single">
<ng-template let-brand>
<ng-container [ngSwitch]="brand.icon && brand.icon.length>0">
<ng-container *ngSwitchCase="true" >
<label class="apply carousel-checkbox">
<input type="checkbox" id="brandCheck" [checked]="brand.isChecked" value="no" name="brand">
</label>
<img [src]="formatLogo(brand.icon)" style="max-width:150px" (click)="brand.isChecked = !brand.isChecked" />
</ng-container>
</ng-container>
</ng-template>
</tshq-carousel>
Please I have this code snippet:
<md-radio-group>
<span *ngFor="let size of item.sizes; let i = index;">
<md-radio-button [value]="size.id" [attr.checked]="i === 0 ? '' : null">
<span class="inline inset text-capitalize" >{{size.name}} </span>
</md-radio-button>
</span>
</md-radio-group>
I want that first md-radio-button will be checked by default, that's why I've added [attr.checked]="i === 0 ? '' : null" following this question but nothing happened. Any ideas how to achieve that please ?
the md-radio-button being a custom component, you cannot check it with an attribute like you would do with an <input type="radio">.
But maybe you could set a default value on your ngModel or formControl...?
<md-radio-group [(ngModel)]="foo">
<span *ngFor="let size of item.sizes; let i = index;">
<md-radio-button [value]="size.id" [attr.checked]="i === 0 ? '' : null">
<span class="inline inset text-capitalize" >{{size.name}} </span>
</md-radio-button>
</span>
</md-radio-group>
ngOnInit(){
this.foo=item.sizes[0].id;
}