I know this issue is very common, but I have done some research already and didn't find any solution for my case, I have tried some stuff like ngZone and setTimeout but won't work.
What I have is a component using ngModel that is updated via a get done by a service using a utility class, as you can check below:
component
ngOnInit(): void {
this.init();
}
private async init() {
this.initModel();
this.initForm();
}
private async initModel() {
await this.getId();
this.getModel();
}
private async getId(): Promise<any> {
return this.route.paramMap.subscribe((params) => {
this._id = params.get('id');
});
}
private async getModel() {
console.log('getModel: '+this._id)
if (this._id) {
console.log('if')
this.operationType = constants.COMPONENT.MAINTAIN.OPERATION_TYPE.PUT;
(await this.session.apiManager.WorkerApi.getWorker(this._id)).subscribe(
(response: any) => {
this.worker = response
console.log('await - ' + this.worker.name)
}
);
console.log('after');
}
else
this.worker = new Worker("");
}
my service class Session
method
public async getWorker(id: string): Promise<Observable<Worker>> {
return await this.api.getData(this.REQUEST_URL + "/" + id);
}
my utility API
class method
public getData(request?: String): Observable<any> {
const requestUrl = this.URL + request;
return this.http.get(requestUrl);
}
What is "funny" is that I have the same code for another model in another component and it works perfectly, but here it won't update my input text (below) after my "get" callback.
<input type="text" class="form-control" name="name" id="name"
required minlength="2" [(ngModel)]="this.worker.name">
Can you help me to understand what is wrong?
Thanks in advance!
I changed the component
to use the toPromise
and my console.log
sequence is working now, although, the model is still not getting updated.
new getModel()
private async getModel() {
console.log('getModel: '+this._id)
if (this._id) {
console.log('if')
this.operationType = constants.COMPONENT.MAINTAIN.OPERATION_TYPE.PUT;
this.worker = (await (await this.session.apiManager.WorkerApi.getWorker(this._id)).toPromise());
console.log('toPromise: '+this.worker.name);
console.log('after');
}
else
this.worker = new Worker("");
}
I just realized that I am having trouble to get the input value via my ts code as well, it just proves that the problem is with my two-way data bind (I guess). When I call the this.worker.name
on my onSubmit
event, the model is empty even though the input is filled.
It makes me wonder if the issue's title is wrong or not... Maybe "Two-way ngModel data binding not working" fits better...
Well, I figured it out when creating a stackblitz as suggested by @H3AR7B3A7 and @Raphaël Balet. What was happening is that I had an extra HTML code using a [formGroup]
:
<form novalidate #form="ngForm" [formGroup]="formGroup" (ngSubmit)="onSubmit(form)">
It means, I was trying to use both two-way data binding with ngModel AND angular reactive forms, and somehow angular was getting lost on it and my model was not working. All I needed to do was remove the [formGroup]="formGroup"
and it worked perfectly.
Also, a tip for the future viewers, the stackblitz helped me providing more precise error messages than my browser, so it helped me with other errors in my application such as null injections.