I have a form connected to models with NgModel
as follows:
<form #orderForm="ngForm" (ngSubmit)="onSubmit(orderForm)">
<ion-list class="contact_view">
<ion-item>
<ion-label stacked>{{ 'ADDRESS_LINE_1' | translate }}</ion-label>
<ion-input type="text" required placeholder="{{ 'ADDRESS_LINE_1_PLACEHOLDER' | translate }}" clearInput="true" name="addressLineOne" [(ngModel)]="order.addressLineOne"></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>{{ 'ADDRESS_LINE_2' | translate }}</ion-label>
<ion-input type="text" placeholder="{{ 'ADDRESS_LINE_2_PLACEHOLDER' | translate }}" clearInput="true" name="addressLineTwo" [(ngModel)]="order.addressLineTwo"></ion-input>
</ion-item>
This has been working well for me when I was using it as one direction binding from the view to the model.
Now, I want to be able to update the input value from the code, as follows:
ionViewDidEnter() {
// attempt to load order from memory
this.storageService
.get<Order>(StorageKeys.ShippingDetails)
.then(order => {
// if order was loaded
if (order) {
// test
this.order.addressLineOne = "aaaa"; // test
// update UI components
//this.changeDetectorRef.markForCheck(); // not working
//this.changeDetectorRef.detectChanges(); // not working
// run inside ngZone to update UI
//this.ngZone.run(() => {
// init order from memory
//this.order.addressLineOne = "bbbb"; // not working
// });
}
});
}
The AddressLineOne
is only updated when one of the inputs is focused.
I tried changeDetectorRef.markForCheck()
,detectChanges()
and running inside ngZone
but it doesn’t work.
Can someone point me in the right direction?
Use your code in "ionViewDidEnter()"
In constructor, not ion “ionViewDidEnter()”
still doesn’t update unless I focus on some input
add you full component code please
import { NgForm } from '@angular/forms/src/directives';
import { Component, ChangeDetectionStrategy, NgZone } from '@angular/core';
import { LoadingController, NavController, ViewController, NavParams } from 'ionic-angular';
import { Observable } from 'rxjs/rx';
import { TrackPage } from '../pages';
import { TrackingIdentifier, TrackingIdentifierType, Order } from '../../models/models';
import { ApiService, LoadingService, StorageService, StorageKeys, IAppState } from '../../shared/shared';
import { BidActions } from '../../actions/actions';
import { Store } from '@ngrx/store';
import { GoogleAnalytics } from '@ionic-native/google-analytics';
// import { FormBuilder, FormGroup, Validator, Validators } from '@angular/forms';
import { TranslateService } from 'ng2-translate';
@Component({
selector: 'page-OrderPage',
templateUrl: 'OrderPage.html',
})
export class OrderPage {
// private orderForm: FormGroup;
private bidId: number;
private order: Order;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public viewCtrl: ViewController,
public ApiService: ApiService,
public loadingService: LoadingService,
public storageService: StorageService,
private translate: TranslateService,
private ngZone: NgZone,
private store: Store<IAppState>,
private bidActions: BidActions,
private analytics: GoogleAnalytics) {
// private formBuilder: FormBuilder
// extract bid id
this.bidId = this.navParams.data as number;
// init default order
this.order = new Order(this.bidId);
this.storageService
.get<Order>(StorageKeys.ShippingDetails)
.then(order => {
// if order was loaded
if (order) {
// run inside ngZone to update UI
this.ngZone.run(() => {
// init order from memory
this.order.addressLineOne = "aaaa";
//this.order = new Order(this.bidId, order);
});
//this.order.addressLineOne = "aaaa";
}
});
}
ionViewDidLoad() {
// track page in analytics
this.analytics.trackView("Order Page");
}
ionViewDidEnter() {
// attempt to load order from memory
// this.storageService
// .get<Order>(StorageKeys.ShippingDetails)
// .then(order => {
// // if order was loaded
// if (order) {
// // run inside ngZone to update UI
// this.ngZone.run(() => {
// // init order from memory
// this.order = new Order(this.bidId, order);
// });
// //this.order.addressLineOne = "aaaa";
// }
// });
}
onSubmit(form: NgForm){
// place order
this.placeOrder();
}
placeOrder() {
// show loading
this.loadingService.present();
// track
this.analytics.trackEvent('Bid', 'Ordered');
// place order
this.ApiService.placeOrder(this.order)
.subscribe(data => {
// extract transaction id from response
let transactionid = data.order.transactionId;
// extract update bid from response
let bid = data.order.bid;
// update bid in data store
this.store.dispatch(this.bidActions.updateStatus(bid));
// go to tracking page
this.track(transactionid);
}, err => {
// dismiss loader
this.loadingService.dismiss();
// TODO: show error message to user
});
// save shipping details for future orders
this.storageService.set(StorageKeys.ShippingDetails, this.order);
}
track(transactionId: number) {
// pop this page from the navigation stack
this.navCtrl.pop();
// go to order page
this.navCtrl.push(
TrackPage,
new TrackingIdentifier(transactionId, TrackingIdentifierType.Transaction)
);
}
}
you don’t need NgZone for updating UI
using [(NgModel)] set to 2 way bindings
Try this code in your constructor:
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public viewCtrl: ViewController,
public ApiService: ApiService,
public loadingService: LoadingService,
public storageService: StorageService,
private translate: TranslateService,
private ngZone: NgZone,
private store: Store<IAppState>,
private bidActions: BidActions,
private analytics: GoogleAnalytics) {
let self = this;
// private formBuilder: FormBuilder
// extract bid id
this.bidId = this.navParams.data as number;
// init default order
this.order = new Order(this.bidId);
this.storageService
.get<Order>(StorageKeys.ShippingDetails)
.then(order => {
// if order was loaded
if (order) {
self.order.addressLineOne = "Order Loaded";
} else {
self.order.addressLineOne = "Order Not Loaded";
}
});
}```
Thanks for the reply. as you can see in the original post, I do use
[(ngModel)]="order.addressLineOne"
for two way binding but it still doesn’t update.
Not sure what self
is but I can’t seem to use it. I get the following error:
Property ‘order’ does not exist on type ‘Window’.
self is reference if this.
try this code:
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public viewCtrl: ViewController,
public ApiService: ApiService,
public loadingService: LoadingService,
public storageService: StorageService,
private translate: TranslateService,
private ngZone: NgZone,
private store: Store<IAppState>,
private bidActions: BidActions,
private analytics: GoogleAnalytics) {
// private formBuilder: FormBuilder
// extract bid id
this.bidId = this.navParams.data as number;
// init default order
this.order = new Order(this.bidId);
let self = this;
this.storageService
.get<Order>(StorageKeys.ShippingDetails)
.then(order => {
// if order was loaded
if (order) {
self.order.addressLineOne = "Order Loaded";
} else {
self.order.addressLineOne = "Order Not Loaded";
}
});
}
If all this not helped remove the block
this.storageService
.get<Order>(StorageKeys.ShippingDetails)
.then(order => {
// if order was loaded
if (order) {
self.order.addressLineOne = "Order Loaded";
} else {
self.order.addressLineOne = "Order Not Loaded";
}
});
and write only
this.order.addressLineOne = "Test";
none of the above worked … maybe this is an issue with ionic?
No i use form without any problem.
I suggest for you to use FormBuilder Docs
Hi, sorry for the simple answer, but does this occur when you do ionic run, and ionic build ?
Some css classes doesn’t work in dev mode.
François
UPDATE
// THIS LINE WORKS
this.order.addressLineOne = "aaba";
this.storageService
.get<Order>(StorageKeys.ShippingDetails)
.then(order => {
// if order was loaded
if (order) {
// THIS LINE DOESN"T WORK
this.order.addressLineTwo = "aaaa";
// update UI components
this.changeDetectorRef.markForCheck();
}
});
When the model is updated from an async callback it doesn’t work