I have a form with some input fields.
When I submit the form I want to add a row to my table dataSource
with the new data.
I have a component for the form that looks like that:
FORM HTML
<form (submit)="submitForm($event)">
<app-form-element align="center" *ngFor="let el of fields| keyobject" [value]="el.value.value" [type]="el.value.type">
</app-form-element>
<button>Save User</button>
</form>
FORM TS
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css'],
})
export class FormComponent implements OnInit {
fields!: object;
constructor() { }
ngOnInit(): void {
this.newForm();
}
newForm() {
this.fields = [{ value: "Name", type: "text" },
{ value: "Surname", type: "text" },
{ value: "Email", type: "email" }];
}
tbc = new TableComponent;
submitForm(event: any) {
let newUser = new User();
newUser.name = event.target.Name.value;
newUser.surname = event.target.Surname.value;
newUser.email = event.target.Email.value;
this.tbc.addValue(newUser);
event.preventDefault();
}
}
export class User {
name!: string;
surname!: string;
email!: string;
}
TABLE HTML
<table *ngIf="show">
<tr>
<th *ngFor="let column of headers">
{{column}}
</th>
<th>Commands</th>
</tr>
<tr *ngFor="let row of dataSource | keyobject; let i = index">
<td *ngFor="let col of headers">
{{row.value[col]}}
</td>
<td>
<button type="button" (click)="deleteValue(i)">Delete</button>
</tr>
</table>
TABLE TS
export class TableComponent implements OnInit {
headers = ['name', 'surname', 'email'];
dataSource: any = [
{ id: 1, name: "test", surname: 'test', email: "[email protected]"},
];
ngOnInit(): void {
}
addValue(user: User) {
let id = this.dataSource.length 1;
this.dataSource = [...this.dataSource, { id: id, name: user.name, surname: user.surname, email: user.email, save: false }];
this.reload();
}
deleteValue(id: any) {
this.dataSource.splice(id, 1);
this.reload();
}
public show = true;
reload() {
this.show = false;
setTimeout(() => this.show = true);
}
}
When I call the addValue
function in the Form.ts it works but the dataSource doesn't get updated.
Debugging the code everything works and it looks like the record is being added to the dataSource but the table dataSource doesn't actually have the new record so it doesn't get displayed.
Notice that my deleteValue
is working fine and is deleting the row from the dable and from the dataSource
I'm new to angular so any help is appreciated
CodePudding user response:
Even though, the other solution of the changeDetector might work, it's not the best approach to tell angular to refresh. It's better to instead, just put your code in a way that angular will notice that needs to change.
I believe that in angular, a push into the array, it's not detected as a new change.
I think instead of doing the push, you could do the following:
this.dataSource = [...this.dataSource, { id: id, name: user.name, surname: user.surname, email: user.email}]
Basically, you would create a new array that contains the old array the new data.
Anyways, to be sure this is a correct answer, could you provide the actual code you have, not a small cut of it, with both TS and HTML Templates ?
CodePudding user response:
I think the problem is that the changes on dataSource
array from your child component are not automatically detected on push. You can force the change detection using detectChanges
from ChangeDetectorRef
:
@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TableComponent implements OnInit {
contructor(
private cdr: ChangeDetectorRef
) {}
dataSource: any = [
{ id: 1, name: "test", surname: 'test', email: "[email protected]"},
];
addValue(user: User) {
let id = this.dataSource.length 1;
this.dataSource.push({ id: id, name: user.name, surname: user.surname, email: user.email});
this.reload();
}
public show = true;
reload() {
// here you can force the change detection
this.cdr.detectChanges();
...
}
}