How to use *Ngfor in an other *Ngfor - html

I am trying to create a checkbox for each element of an array "lesCriteres".
Then I want each of these checkboxes to be checked if its value is in the table "actif.lesCriteresActifs"
Here is the code I want but it does not work as I want
<div class="checkbox-inline" *ngFor="let l of lesCriteres">
<div *ngFor="let a of actif.lesCriteresActifs">
<label></label>
<input type="checkbox" (change)="onChangeEvent(l.code, $event.target.checked)" [checked]="a.critere.code==l.code"> {{l.code}}<br>
</div>
</div>
MODELS
actif model
import {TypeActif} from './model.type-actif';
import {CritereActif} from './model.critere-actif';
export class Actif{
ref: string;
nom: string = '';
type_actif: TypeActif = new TypeActif();
lesCriteresActifs: Array<CritereActif> = new Array<CritereActif>();
}
CritereActif model
import {Actif} from './model.actif';
import {LesCriteres} from './model.les-criteres';
import {LesValeurs} from './model.les-valeurs';
export class CritereActif{
id: number;
actif: Actif = new Actif();
critere: LesCriteres = new LesCriteres();
valeur: LesValeurs = new LesValeurs();
}
LesCriteres model
export class LesCriteres{
code: string = null;
nom: string = '';
}
RESULT
i have this when i execute my code :
but i want't something like this :

This should work (using includes() method, without additional *ngFor):
<div class="checkbox-inline" *ngFor="let l of lesCriteres">
<label></label>
<input type="checkbox" (change)="onChangeEvent(l.code, $event.target.checked)" [checked]="actif.lesCriteresActifs.includes(l)"> {{l.code}}<br>
</div>
About includes method: https://www.w3schools.com/jsref/jsref_includes_array.asp
EDIT:
This solution comes to mind.
In .ts file of your component, inside class declare a function:
containsCode = (code) => {
for (let a of this.actif.lesCriteresActifs) {
if (a.critere.code === code) {
return true
}
}
return false
Then in .html file:
<div class="checkbox-inline" *ngFor="let l of lesCriteres">
<label></label>
<input type="checkbox" (change)="onChangeEvent(l.code, $event.target.checked)" [checked]="containsCode(l.code)"> {{l.code}}<br>
</div>

Related

How to set value to 2d array in input tag html

I am work in angular. I would like the user to be able to set up lesson subjects and a specific number of hours for a given student group.
group.component.html:
<!--list of groups -->
<div *ngFor="let group of groups">
<div><button (click)="Edit()">Edit group</button></div>
<!--mode without edit -->
<div *ngIf="edit==false">
<tr>Name:{{group.name}}</tr>
</div>
<!--mode with edit -->
<div *ngIf="edit==true">
<tr>Name:<input type="text" value="{{group.name}}" [(ngModel)]="group.name m[ngModelOptions]="{standalone: true}"></tr>
<!--add Subject and set amount hours -->
<!-- add one or more empty subject, select subject and set amount hours-->
<tr>Subjects:</tr>
<button (click)="addSubject()">add</button>
<!-- list of subjects for one group-->
<form>
<div *ngFor="let sub of yourSubjects; let i=index">
<select class="form-control">
{{group.name}}
<option *ngFor="let sub2 of subjectsList" value="{{sub2.name}}">{{sub2.name}}</option>
<input type="hide" [(ngModel)]="groupItem.subjects[[i][0]]" [ngModelOptions]="{standalone: true}">
</select>
<!-- set amount hours for one subject -->
<!--kind of lessons, for one subject -->
Lecture(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][1]]" [ngModelOptions]="{standalone: true}">
workout(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][2]]" [ngModelOptions]="{standalone: true}">
laboratory(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][3]]" [ngModelOptions]="{standalone: true}">
<button (click)="deleteSubject()">Delete</button>
</div>
<!--send data to function -->
<input type="submit" value="Submit" (click)="Edit();updateGroup({id : group.id, name : group.name, yourAllSubjects : groupItem.subjects})">
</form>
</div>
</div>
group.component.ts:
import { Component, OnInit } from '#angular/core';
import {GroupsApiService, RoomsApiService, SubjectsApiService} from "../../../api.services";
import {Groups} from "../../../models/groups.model";
import {Subjects} from "../../../models/subjects.model";
#Component({
selector: 'app-group',
templateUrl: './group.component.html',
styleUrls: ['./group.component.css']
})
export class GroupComponent implements OnInit {
constructor(private groupsApiService:GroupsApiService, private subjectsApiService: SubjectsApiService) { }
groups:Groups[] = [] //list of groups from database
subjectsList:Subjects[]=[] //list of all subjects
groupItem:Groups = new Groups('',1) //one group object
subject:Subjects = new Subjects('',1) // one subject object
number:number = history.state?.data?.title // index one group from groups.component
ngOnInit(): void {
this.groupsApiService.getGroup(this.number).subscribe(data => this.groups = data);
this.subjectsApiService.getSubjects().subscribe(data=>this.subjectsList=data);
// get data from database, data of one group, data of subjects, function from apiservice
}
yourSubjects: Subjects[]=[]; //list of subject for one group
edit=false //say when edit mode on/off
//edit mode
Edit() {
this.edit = !this.edit;
}
// function in html, it send data to database
updateGroup({id, name, yourSubjects}: { id: number, name: string, yourAllSubjects: [][] }){
var arrStr = encodeURIComponent(JSON.stringify(yourSubjects));
this.groupsApiService.editGroup(id,name,arrStr).subscribe()
}
addSubject() {
this.yourSubjects.push(this.subject)
}
deleteSubject(){
this.yourSubjects.pop()
}
}
group.model.ts
export class Groups {
constructor(
public name: string,
public id: number,
public subjects:[][]
) { }
}
apiservice
#Injectable()
export class GroupsApiService {
constructor(private http: HttpClient) {
}
getGroups(): Observable<Groups[]> {
return this.http.get<Groups[]>(`${API_URL}/management/groups`)
}
editGroup(id:number,name: string, yourSubjects?:string){
return this.http.get<Groups[]>(`${API_URL}/management/groups/group/editgroup?id=${id}&name=${name}&subjects=${yourSubjects}`)
}
getGroup(id:number): Observable<Groups[]> {
return this.http.get<Groups[]>(`${API_URL}/management/groups/group?id=${id}`)
}
}
Summary:
The user selects one group and can edit it. He can add specific subjects to it, then specify the number of hours for the types of lessons in a given subject. The number of hours is specified in three text inputs. Then the array saves itself. The array is to keep the names of the items and the individual hours. e.g:
groupItem.subjects[[i][0]]= physics
groupItem.subjects[[i][1]] = 11
groupItem.subjects[[i][2]] = 12
groupItem.subjects[[i][3]] = 30
groupItem.subjects = [{'physics','11','20','30'},{'math','11','20','30'},{'biology','11','20','30'}]
In html have function:
```
<input type="submit" value="Submit" (click)="Edit();updateGroup({id : group.id, name : group.name, yourAllSubjects : groupItem.subjects})">
and in groyp.component.ts:
```
updateGroup({id, name, yourSubjects}:{ id: number, name: string, yourAllSubjects: string[][] })
{ var arrStr = encodeURIComponent(JSON.stringify(yourSubjects)); this.groupsApiService.editGroup(id,name,arrStr).subscribe()
}
Next url is send to backend. Unfortunalety i have null in subject:
http://localhost:5000/management/groups/group/editgroup?id=6&name=example&subjects=[]'
what to do to send arrays correctly in url?

How to validate dynamic form in angular

Below is my code. According to the loop count, fName will increase. currently I am using ng-bootstrap-form-validation for validation. The issue if I validate using formControlName that's not working it's duplicating if one field(fName) is correct all the fields become correct.
Below is my HTML code,
<form [formGroup]="formGroup" (validSubmit)="onSubmit()">
<div class="results-traveler" *ngFor="let item of createLoopRange(selectedDataDetails[0].Adult); let ii= index;">
<div class="row">
<div class="col-12 heading" *ngIf="ii == 0 else travelCount">Traveller {{ii}}</div>
<div class="col-6 M-full-div">
<label>First Name</label>
<div class="inputContainer form-group">
<input class="InputField form-control" type="text" placeholder="Type Here" formControlName="fName" id="fName_{{i}}" />
</div>
</div>
</div>
</div>
<a class="SearchBtn" type="submit">CONTINUE</a>
</form>
Below is the typescript code I am using,
ngOnInit(): void {
this.bookingDetailsValidate();
}
bookingDetailsValidate() {
this.formGroup = new FormGroup({
fName: new FormControl('', [
Validators.required,
Validators.pattern(/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
])
});
}
onSubmit() {
console.log(this.formGroup);
}
Can anyone please guide me on how to do this. Thanks.
for fName use FormArray then add FormControl to FormArray and you can validate FormArray and every FormControl inside FormArray
example:
this.formGroup = new FormGroup({
fName: new FormArray([], [
Validators.required
])
});
...
const arrayOfNameControl = this.formGroup.get('fName') as FormArray
arrayOfNameControl.insert(0, new FormControl('',[
Validators.required,
Validators.pattern(/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
]));
You need form array here. Please refer the link.
Angular form array

Angular NgFor loop 2 arrays of objects

I want to loop through two different arrays with ngFor and display them in html.
<div class="form-check ml-5" *ngFor="let item of competencias.competencias; let i = index">
<input class="form-check-input" type="checkbox" [value]="item.id [(ngModel)]="arrayCompetencias[i].checked">
<label class="form-check-label">
<strong> {{ item.id }} </strong> : {{ item.descripcion}}
</label>
</div>
Those 2 arrays has the same length but I want to combine them as to show separate data.
First array has a list of data just to display and is fine.
Second array arrayCompetencias I want just to see if user check the checkbox or not and save it as ngModel.
When trying to get the parameter data in arrayCompetencias[i].checked it through me an error that the field is undefined, but I am initializing them before.
First Array
competencias = [{id: string, descripcion: string}]
Second Array
arrayCompetencias = [{checked: boolean, id: string}]
[(ngModel)]="arrayCompetencias[i].checked">
How can i read only this field into the array and set according User checked or not
I fixed some typos on your code and added some edits.
Try to use this example and it should work perfectly with you.
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
competencias = [{id: "1", description: "This is a description"}]
arrayCompetencias = [{checked: true, id: "1"}]
}
<div *ngFor="let item of competencias; let i = index">
<input type="checkbox"
[value]="item.id"
[checked]="arrayCompetencias[i].checked"
(change)="arrayCompetencias[i].checked = !arrayCompetencias[i].checked">
<label>
<strong> {{ item.id }} </strong> : {{ item.description}}
</label>
</div>
Nothing I have changes only a problem in your data.
You can check the code here

How to display array item in Angular

I am a newbie in Angular, I create an array but I have problem to display it.
When I display the array item it is blank.
write.component.html:
<div class="data">
<li> Name: <input type="text" [(ngModel)]="name" placeholder="Please enter Name" ></li>
<li> Age:<input type="text" [(ngModel)]="age" placeholder="Please enter Age" class="age"></li>
<li>College:<input type="text" [(ngModel)]="college" placeholder="Please enter College" ></li>
</div>
<h2>Student</h2>
<ul class="details">
<li>
<span class="badge" *ngFor="let student of students"> // display array item
{{student.name}}{{student.age}}{{student.college}}</span>
</li>
</ul>
.ts
export class WriteComponent implements OnInit {
name : string;
age : number;
college : string;
students : Array<any>; // declare array
}
write-service.ts
import { Injectable } from "#angular/core";
#Injectable()
export class HomeService {
private students = new Array<any>( //array details
{
name:"dwq",
age:12,
college:"2321"
}
)
}
After you create the service you have to inject that service to your component like this
constructor(private homeServ:HomeService) { }
then the service will be avilable in the componnet you can get the data
ngOnInit(){
this.students = this.homeServ.getStudents();
}
demo 🚀
you can remove the injectable decorator from the service if the service has no dependency
read more about angular services 👉 her

Uncaught Error: Can't resolve all parameters for Component: ([object Object]?)

So, before You read the whole error stack, keep in mind that at this time I cant pinpoint the exact piece that causes the problem. However, I will disclose the code below the error stack. So, my only question is: what parameters can't be resolved?
If you like, you can test my application for yourself. It is a simple default angular 6 application with all the default settings you get from the following command below:
ng new app-name
let's begin with the error. The application starts like normal. When I try to run the code, this error pops up: Uncaught Error: Can't resolve all parameters for Component: ([object Object]?). You can read the full error stack below.
Uncaught Error: Can't resolve all parameters for Component: ([object Object]?).
at syntaxError (compiler.js:1016)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (compiler.js:10917)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata (compiler.js:10810)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata (compiler.js:10429)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.loadDirectiveMetadata (compiler.js:10291)
at compiler.js:23865
at Array.forEach (<anonymous>)
at compiler.js:23864
at Array.forEach (<anonymous>)
at JitCompiler.push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (compiler.js:23861)
syntaxError # compiler.js:1016
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata # compiler.js:10917
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata # compiler.js:10810
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata # compiler.js:10429
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.loadDirectiveMetadata # compiler.js:10291
(anonymous) # compiler.js:23865
(anonymous) # compiler.js:23864
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._loadModules # compiler.js:23861
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents # compiler.js:23839
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync # compiler.js:23799
push../node_modules/#angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync # platform-browser-dynamic.js:143
push../node_modules/#angular/core/fesm5/core.js.PlatformRef.bootstrapModule # core.js:4352
./src/main.ts # main.ts:11
__webpack_require__ # bootstrap:76
0 # main.ts:12
__webpack_require__ # bootstrap:76
checkDeferredModules # bootstrap:43
webpackJsonpCallback # bootstrap:30
(anonymous) # main.js:1
As you see, there is no easy way of telling which part of my typescript is causing the problem. However, The application runs fine without the code in component.ts shown below. So, there is definitely something wrong with my typescript component.ts
the component.ts is shown below:
import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, Directive} from '#angular/core';
import { FormGroup } from '#angular/forms';
import { DefineBusinessRuleService } from '../services/define/define-business-rule.service';
import { DefineBusinessRuleNamespace } from '../model/business-rule-namespace';
#Component({
selector: 'app-define-business-rule',
templateUrl: './define-business-rule.component.html',
styleUrls: ['./define-business-rule.component.css']
})
export class DefineBusinessRuleComponent implements OnInit {
// interfaces
headers : Headers;
output: any;
#Input() minValue: string;
#Input() maxValue: string;
#Input() attribute : Array<string>;
#Input() table : Array<string>;
submitted = false;
#Input() businessRuleType : Array<string>;
ruletypes : Array<string>;
ruletype : string;
constructor(
private defineBusinessRuleService: DefineBusinessRuleService
,private model : any
) {
this.table = ['table1', 'table2', 'table3'];
this.attribute = ['attribute1', 'attribute2', 'attribute3'];
this.ruletypes = [
// atrribute
'AttributeRange',
'AttributeCompare',
'AttributeList',
'AttributeOther',
'TupleCompare',
'TupleOther'
]
model = {
minValue : 5,
maxValue : 10,
name : 'RangeRule',
description : 'This is a Range Rule',
table1 : this.table[0],
column1 : this.attribute[2],
errorMsg : 'Error message'
};
}
get diagnostic() { return JSON.stringify(this.model); }
defineNewBusinessRule() {
//this.model = new DefineBusinessRuleService(42, 50, '', '', '', '', '');
}
saveAttributeRangeRule(){
this.output = {
database_id : 1,
minValue : this.minValue,
maxValue : this.maxValue,
table1 : this.table,
column1 : this.attribute
}
this.output.stringify;
this.defineBusinessRuleService.saveAttributeRangeRule(this.output);
}
saveAttributeCompareRule(){
this.output = {
database_id : 1,
table1 : this.table,
//table2 : this.table2,
column1 : this.attribute,
//column2 : this.attribute2,
//value : this.value
}
this.output.stringify;
//this.defineBusinessRuleService.saveAttributeCompareRule(this.output);
}
ngOnInit(){
}
onSelect(){
}
onSubmit() {
this.submitted = true;
this.ruletype = this.ruletypes[0];
switch(this.ruletype){
case "AttributeRange" : {
this.saveAttributeRangeRule();
break;
};
case "AttributeCompare" : {
this.saveAttributeCompareRule();
break;
};
}
}
}
Thanks for reading this! If you are visually orientated like me, then this form might help you understand what this code should do. However, it's off topic, since i'm certain enough that it doesn't cause operational problems in angular. keep that in mind!
the related html form is shown below
<br>
<br>
<main role="main" class="container">
<div class="container">
<h1>Define Business Rule</h1>
<form (ngSubmit)="onSubmit()" #defineBusinessRuleForm="ngForm">
<div class="form-group">
<label for="minValue">Minimum Value</label>
<input type="text" class="form-control" id="minValue">
</div>
<div class="form-group">
<label for="maxValue">Maximum Value</label>
<input type="text" class="form-control" id="maxValue">
</div>
<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">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Name is required
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<input type="text" class="form-control" id="description" required>
</div>
<div class="form-group">
<label for="table">Table</label>
<select class="form-control" id="table" required>
<option *ngFor="let tbl of table" [value]="table">{{tbl}}</option>
</select>
</div>
<div class="form-group">
<label for="attribute">Attribute</label>
<select class="form-control" id="attribute" required>
<option *ngFor="let attr of attribute" [value]="attribute">{{attr}}</option>
</select>
</div>
<div class="form-group">
<label for="errorMsg">Error Message</label>
<input type="text" class="form-control" id="errorMsg" required>
</div>
<button type="submit" class="btn btn-success" [disabled]="!defineBusinessRuleForm.form.valid">Submit</button>
<button type="button" class="btn btn-default" (click)="defineNewBusinessRule(); defineBusinessRuleForm.reset()">Define New BR</button>
</form>
</div>
</main>
The error is in the model definition location.
private model: any should be defined as a parameter outside of a constructor.
By placing it in the constructor, the compiler is trying to resolve any class, and, naturally is unable to do so.
Modify your code this way:
export class DefineBusinessRuleComponent implements OnInit {
private model : any
constructor() {
this.model = {
// your model definition
};
}
// rest of the code
}