Validation not working for radio button in angular - html

Validation not working for radio button in Angular.
When radio button is not selected, form is getting submitted.
Also not showing error.
HTML Code
<form [formGroup]="feedbackFormWithArray" (ngSubmit)="submitData()">
<table class="res-tbl">
<tbody formArrayName="skills" class="tbl">
<tr class="skill-tr table-data" *ngFor="let skill of skills; let i = index">
<td class="table-data res-td tbl-border skill-td">
<b value="skill.skillId"><span class="text-danger">*</span>{{skill.skillName}}<span>:</span></b><p class="skill-description-p"> {{skill.skillDescription}}</p>
</td>
<td class="table-data center rating-td">
<input type="radio" formControlName="{{ i }}" [value]="3" />
</td>
<td class="table-data center rating-td">
<input type="radio" formControlName="{{ i }}" [value]="2" />
</td>
<td class="table-data center rating-td">
<input type="radio" formControlName="{{ i }}" [value]="1" />
</td>
</tr>
</tbody>
<div *ngIf="(submitted && skills.invalid)">
<small *ngIf="skills.errors?.required" class="text-danger">Please select Skills</small>
</div>
</table>
<Button type="submit" [disabled]="feedbackFormWithArray.invalid" class="btn button-btn" >{{feedbackId ? 'Update' : 'Create'}}</Button>
</form>
TS Code
import { Validators } from '#angular/forms';
submitted : boolean = false;
this.feedbackFormWithArray= this.fb.group({
skills: this.fb.array(
this.skills.map((t) => {
this.fb.control(t);
}), {validators: Validators.required}
)
});
submitData() {
this.submitted = true;
}
How to solve this?
Thank you!

I am gonna guess you have a button inside your form, something like:
component.html
<button (click)="submitData()">Submit</button>
You could add a check to change submitted state like
submitData() {
if (this.feedbackFormWithArray.valid) {
this.submitted = true;
}
if (this.feedbackFormWithArray.invalid) {
// Do something like this.tryToSubmitWithError = true
// Popup to say you cannot submit
// ...
}
}
I think also you wanted to use feedbackFormWithArray instead of skills in the *ngIf below:
<div *ngIf="(submitted && skills.invalid)">
<small *ngIf="skills.errors?.required" class="text-danger">Please select Skills</small>
</div>
That could be like:
<div *ngIf="tryToSubmitWithError && feedbackFormWithArray.invalid">
<small *ngIf="feedbackFormWithArray.errors?.required" class="text-danger">
Please select Skills
</small>
</div>

Related

How to get value as parameter with multiple same input names?

So I have a list in which I loop through and I create the table rows.
#if (Model.TbAuctions != null && Model.TbAuctions.Count > 0)
{
foreach (var item in Model.TbAuctions)
{
<tr>
<td>
<img src="~/images/ebayonly.gif" />
</td>
<td>
#{
<form asp-page="GetSellerListModel" method="post" data-ajax="true" data-ajax-method="post" data-ajax-begin="begin" data-ajax-complete="complete" data-ajax-failure="failed">
<input type="hidden" value="#item.AuctionId" name="auctionId" />
<input id="submitBtn" style="display:none;" type="submit">
#Html.DisplayFor(modelItem => item.AuctionId)
</form>
}
</td>
</tr>
}
}
Code Behind:
public async Task<IActionResult> OnPostAsync(string auctionId)
{
try
{
if (ModelState.IsValid)
{
var itemId = auctionId;
}
}
catch (Exception ex)
{
throw ex;
}
return Page();
}
I have one input hidden field in which I save the value of the AuctionId, so when i click in the a href it clicks the other input via javascript and I send the AuctionId value as a parameter in the Post method. Till now everything is okay, however because the name of the input is always the same, it always takes the first input value regardless of where you click. What can I do here, so I can get the exact value of the input I clicked ?
P.s. I click the input via <a href because I want 'a' tag styling.
You have serveral inputs which ids are submitBtn,you need to make id unique,so that you can click the button which you want.You can do like this:
#{ var i = 0;}
#foreach (var item in Model.TbAuctions)
{
<tr>
<td>
<img src="~/images/ebayonly.gif" />
</td>
<td>
#{
<form asp-page="GetSellerListModel" method="post" data-ajax="true" data-ajax-method="post" data-ajax-begin="begin" data-ajax-complete="complete" data-ajax-failure="failed">
<input type="hidden" value="#item.AuctionId" name="auctionId" />
<input id="submitBtn#(i)" style="display:none;" type="submit">
#Html.DisplayFor(modelItem => item.AuctionId)
</form>
i++;
}
</td>
</tr>
}

Issue when Table with Inputs is inside of a Form

I'm building an Angular application with PrimeNG. I have a form that contains a p-table (list of products) with inputs (quantity and price), when I select the first product from a dialog and enter the inputs (quantity and price), then select a second product, I lose the first quantity and price that enter for the first product.
This issue only happened when putting the table with inputs inside of the form.
Is there a right way to resolve this? My code is below.
HTML:
<form #form="ngForm" (ngSubmit)="valider(form)">
<p-table [value]="object.produits" >
<ng-template pTemplate="header">
<tr>
<th>Code Produit</th>
<th>Quantité</th>
<th>Price</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-produit>
<tr [pSelectableRow]="produit">
<td>{{produit.codeProduit}}</td>
<td>
<input type="text" size="10" pInputText name="quantite" [readonly]="action=='show'" pKeyFilter="num" [ngModel]="produit.quantite" (ngModelChange)="produit.quantite = $event;">
</td>
<td>
<input type="text" size="10" pInputText name="prixUnitaire" [readonly]="action=='show'" pKeyFilter="num" [ngModel]="produit.prixUnitaire"(ngModelChange)="produit.prixUnitaire = $event;">
</td>
</tr>
</ng-template>
<ng-template pTemplate="summary">
<button type="button" (click)="showDialogProduit()" pButton label="Ajouter Produit"></button>
</ng-template>
</p-table>
</form>
<p-dialog header="Liste des produits" [(visible)]="dialogProduit" >
<p-table #dt_produits [value]="produits" selectionMode="multiple" [(selection)]="operationCommodities.produits" >
<ng-template pTemplate="header">
<tr>
<th>Code</th>
<th>Désignation</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-produit>
<tr [pSelectableRow]="produit">
<td>{{produit.codeProduit}}</td>
<td>{{produit.designation}}</td>
</tr>
</ng-template>
<ng-template pTemplate="summary">
<button pButton type="button" label="Terminer" (click)="closeDialogProduit()"></button>
</ng-template>
</p-table>
</p-dialog>
TS:
showDialogProduit() {
this.dialogProduit = true;
}
closeDialogProduit() {
this.dialogProduit = false;
}
Stackblitz Demo:
https://stackblitz.com/edit/primeng-tablebasic-demo-a7bdgm?file=src%2Fapp%2Fapp.component.html
The problem is that input fields don't have a unique name which messes up how ngModel directive works. When I updated the code as follows, it was fixed. Note that the [name] attributes of both input fields are dynamic values based on produit.codeProduit
<tr [pSelectableRow]="produit">
<td>{{produit.codeProduit}} </td>
<td>
<input type="text" size="10" pInputText [name]="'quantite_' + produit.codeProduit" [readonly]="action=='show'" pKeyFilter="num" [ngModel]="produit.quantite" (ngModelChange)="produit.quantite = $event;">
</td>
<td>
<input type="text" size="10" pInputText [name]="'prixUnitaire_' + produit.codeProduit" [readonly]="action=='show'" pKeyFilter="num" [ngModel]="produit.prixUnitaire"(ngModelChange)="produit.prixUnitaire = $event;">
</td>
</tr>
Please check Forked stackblitz with updated code.
As an aside, I recommend you change your implementation to use Angular Reactive Forms instead of ngModel;

How can I use a specific FormControl from a FromArray in my HTML Document?

I'm initializing my FormArray with this code
this.contents.forEach(content=> {
this.formArray.push( new FormControl(content.text, Validators.required));
});
and I want to link one FormControl with my textarea and change it with my ID.
<textarea matInput id="content-textarea" placeholder="Required" [formControlName]="formArray.at(id)"></textarea>
But I get this error message:
ERROR Error: Cannot find control with unspecified name attribute
How can i use a specific FormControl from a FormArray in my HTML Document?
EDIT: I cant use a FormControl if i dont have one. I got this error message because my Content-Array was empty and i tried to use the FormControl.
So i have a different problem. But thanks for your answers :)
What if you directly use formcontrol instead of formcontrolname
<textarea matInput id="content-textarea" placeholder="Required" [formControl]="formArray.controls[0]"></textarea>
demo
I did something like this, can't show demo it's part of the big module:
<tr *ngFor="let file of docInfoForm.controls.Documents.controls; let i = index;" [formGroup]="file" class="form-group">
<td>
<fa class="cust-file-icon" [name]="file.get('Name').value | fileTypeIcon"></fa>
<input [attr.id]="'file-type-' + i" type="hidden" class="form-control" formControlName="Type" placeholder="File Size">
</td>
<td class="left">
<text-control [ctr-id]="'file-name-' + i" [label-text]="'File Name'" formControlName="Name"
[error-text]="'File Name is required'" [mandatory]="true" [form-ctr]="file.controls.Name">
</text-control>
</td>
<td class="left">
<text-control [ctr-id]="'file-desc-' + i" [label-text]="'Description'" formControlName="Description"></text-control>
</td>
<td class="left">
<label for="{{'file-size-' + i}}" class="form-label">
<span class="file-size-label">Size</span>
<span class="file-size-value">{{ file.get('Size').value | fileSize: true }}</span>
<input [attr.id]="'file-size-' + i" type="hidden" class="form-control" formControlName="Size" placeholder="File Size">
</label>
</td>
<td>
<button class="btn btn-outline only-icon btn-round" (click)="removeFile(i)">
<clr-icon shape="times"></clr-icon>
</button>
</td>
</tr>

Radio Button Model returns undefined value when a save button is clicked

I have 2 radio buttons, which I assigned values of '0' and '1' respectively. I need to get the value when I click my Save Button but It returns an Undefined value. Here is my code. What could be my problem?
<tr ng-repeat="item in recruleData">
<td>
{{item.package_name}}
</td>
<td>
<input type="radio" name="radio" ng-model="radio.selectedProductBlock"
value="0" >A<br/>
<input type="radio" name="radio" ng-model="radio.selectedProductBlock"
value="1" > B
</td>
<a class="btn btn-primary pull-right" ng-click="radioValue();">Save</a>
</tr>
my JS Code
$scope.selectedProductBlock;
$scope.radioValue= function(){
alert($scope.selectedProductBlock);
}
You need to define a variable of type boolean inside the object radio,
$scope.radio = {};
$scope.radio.selectedProductBlock = false;
and then
And radioValue function
$scope.radioValue = function(){
console.log($scope.radio.selectedProductBlock);
}
According to your requirement, you need to define radio object in recruleData
each record
Ex :
$scope.recruleData = [
{"package_name" : "package1", "radio":{"selectedProductBlock":""}},
{"package_name" : "package1", "radio":{"selectedProductBlock":""}},
]
And radioValue function
$scope.radioValue= function(item){
alert(item.radio.selectedProductBlock);
}
In addition, you need to give a unique name for each row radio button groups. You can simply achieve that append $index to your radio button name.
HTML Code
<table>
<tr>
<th>Package</th>
<th>Actioins</th>
<th></th>
</tr>
<tr ng-repeat="item in recruleData">
<td>
{{item.package_name}}
</td>
<td>
<input type="radio" name="radio_{{$index}}" ng-model="item.radio.selectedProductBlock"
value="0" >A<br/>
<input type="radio" name="radio_{{$index}}" ng-model="item.radio.selectedProductBlock"
value="1" > B
</td>
<td><a class="btn btn-primary pull-right" ng-click="radioValue(item);">Save</a></td>
</tr>
</table>
Working JSFiddel

How to highlight multiple selected row in angular 4

How to highlight multiple selected row in angular 4 ,
Here I can edit with checkbox and perform other action too. What I am looking is to highlight the row which is checked.
<tbody>
<tr *ngFor='let row of rowData' [ngClass]="{ 'selected': row.selected }">
<td class="text-center>
<input type="checkbox" [(ngModel)]="row.selected" />
</td>
<td>
<input type="text" *ngIf="row.editable" [(ngModel)]="row.name" />
<ng-container *ngIf="!row.editable">{{row.name}}</ng-container>
<!-- You can use span or whatever instead of ng-container-->
</td>
<!-- Repeat for other cells -->
</tr>
</tbody>
It is dead simple simply use angular class directive
<tr *ngFor='let row of rowData' [class.selected]="row.selected">
Now it will add class selected when row.selected is true to the row
To highlight a row, you need to highlight the cells (<td>). From what I know, you can't highlight a row.
Here is the logic :
<tbody>
<tr *ngFor='let row of rowData'>
<td class="text-center" [class.selected]="row.selected">
<input type="checkbox" [(ngModel)]="row.selected" />
</td>
<td [class.selected]="row.selected">
<input type="text" *ngIf="row.editable" [(ngModel)]="row.name" />
<ng-container *ngIf="!row.editable">{{row.name}}</ng-container>
<!-- You can use span or whatever instead of ng-container-->
</td>
<!-- Repeat for other cells -->
</tr>
</tbody>
HTML :
<tr *ngFor="let record of mf.data; let i = index" [attr.data-index]="i" [className]=" selectedAll==true || selectedRow.indexOf(i)>-1 ?
'pointer selected' : 'pointer'">
<td class=" text-left" width="20">
<input type="checkbox" (change)="selectAll(i)" [checked]="selectedAll == true">
</td>
...
</tr>
TS :
export class YourComponent implements OnInit {
selectedRow: any;
selectedAll: boolean = false;
constructor(){
this.selectedRow = [];
}
selectAll(index) {
if (typeof (index) == 'undefined') {
this.selectedAll = !this.selectedAll;
this.selectedRow = [];
} else {
this.selectedRow.push(index);
}
}
HTML :
<tr *ngFor="let record of mf.data; let i = index" [attr.data-index]="i" [className]=" selectedAll==true || selectedRow.indexOf(i)>-1 ?
'pointer selected' : 'pointer'">
<td class=" text-left" width="20">
<input type="checkbox" (change)="selectAll(i)" [checked]="selectedAll == true">
</td>
...
</tr>
TS :
export class YourComponent implements OnInit {
}