问题
I want to make a student able to choose several workshops in a dynamic number of school subjects
1.- I have a config array, this array have the number of options of the student will choose for every subject
let configarray = {initdate: 2019-07-01, subjectnumber: 4};
In this example for every subject the student will be able to choose 4 options.
let b = this.FormGuardar.get("opciontaller") as FormArray;
for (let i = 0; i < configarray.subjectnumber; i++) {
let preregistro = this._fb.group({
preregistroid: [],
alumnoporcicloid:[],
tallercurricularid: []
});
b.push(preregistro);
this.arrayopcion.push({ taller: this.tallerselect }); //tallerselect will display
the options of every subject every subject will have a diferent options
Also when i select a options this is my code for erase the selected option in the other selects in the configurations.
selectedTaller(id, index) {
let seleccionados = [];
let array = this.FormGuardar.get("opciontaller").value;
for (let a of array) {
if (a.tallercurricularid) {
seleccionados.push(a.tallercurricularid);
}
}
let disponibles = this.SelectTaller.filter(function (item) {
return seleccionados.indexOf(item.tallercurricularid) == -1;
});
for (let i = 0; i < this.arrayopcion.length; i++) {
let data = [...disponibles],
control = ((this.FormGuardar.controls.opciontaller as FormArray).controls[i] as FormGroup).controls.tallercurricularid as FormControl,
seleccionado = this.SelectTaller.find(x => x.tallercurricularid == control.value);
(((this.FormGuardar.controls.opciontaller as FormArray).controls[i] as FormGroup).controls.clasificadorparaescolarid as FormControl).setValue(seleccionado ? seleccionado.clasificadorparaescolaresid.clasificadorparaescolaresid : null);
seleccionado ? data.push(seleccionado) : null;
this.arrayopcion[i].taller = data;
seleccionado ? control.setValue(seleccionado.tallercurricularid) : null;
}
}
The question here is how can i make this code work for a dynamic number of subjects with a dynamic options for every workshops?
回答1:
To erase the options, see stackoverflow question
If you choose create on-fly the list, you can make something like see stackblitz
You has a recursive function that take as argument an index, an array of controls and an array with the options to choose -in this case I choose between a list of languages-
getLang(i, array, languageList) {
return i == 0 ? languageList :
this.getLang(i - 1, array, languageList.filter(x => x.name != array[i - 1].value))
}
If you has a function like
createStudent() {
const auxiliar = new Array(this.configarray.subjectNumber).fill('')
return new FormGroup(
{
name: new FormControl(),
options: new FormArray(auxiliar.map(x => new FormControl()))
}
)
}
You can has in ngOnInit some like
this.formArray=new FormArray([]);
this.formArray.push(this.createStudent())
this.formArray.push(this.createStudent())
And our form is like
<form *ngIf="formArray" [formGroup]="formArray">
<div *ngFor="let form of formArray.controls">
<div [formGroup]="form">
<input formControlName="name">
<div formArrayName="options">
<div *ngFor="let a of form.get('options').controls;let i=index" >
<select [formControlName]="i">
<option value="null" disabled>Select Language</option>
<option *ngFor="let lang of
getLang(i,form.get('options').controls,languageList)"
[value]="lang.name" >{{lang.name}}</option>
</select>
</div>
</div>
</div>
<hr/>
</div>
</form>
Updated We need check not possible choose the same language, so we subscribe to changes of the arrays options. So, if we choose e.g. German,Doraki,Spanish and French, and after replace German by Spanish, the 3th options becomes null
this.formArray.controls.forEach(form => {
form.get('options').valueChanges.subscribe(res => {
res.forEach((x, index) => {
if (index > 0 && res.slice(0, index).find(a=>a==x))
(form.get('options') as FormArray).at(index).setValue(null, { emit: false })
})
})
})
来源:https://stackoverflow.com/questions/57049514/dynamic-form-array-with-dynamic-options