Reputation: 134
I'm confused about how widget binding works, according to google document, a two-way binding works:
1. when use UI widget to update model data to server side.
2. "any change to a name on the server automatically updates the text displayed in the text box"
However, this is not what I see, I cannot see that widget (ex. textbox) value changes following a server side data update.
I did a test in the official sample Registration Form, there is a list of all Registration items. My testing setting is to update the first entry (Id=1)'s email address by entering a new email and have two buttons to update info: button 'CHANGE_CLIENT' uses a client script, and button 'CHANGE_SERVBER' uses a server script.
CHANGE_CLIENT code is client script in onClick() event:
var item = widget.datasource.items.filter( a => a.Id == 1 )[0];
item.Email = widget.parent.descendants.TextBox1.value;
Result:
a click on the button, new value is updated into list's 1st item as expected. A screenshot for info
CHANGE_SERVER code has both client script and server script:
client script:
function c(newvalue) {
google.script.run.withSuccessHandler(function() {console.log('ok');}).withFailureHandler(function() {console.log('nono');}).change(newvalue);
}
server script:
function change(newvalue) {
var record = app.models.Registration.getRecord('1');
record.Email = newvalue;
app.saveRecords([record]);
}
Result:
a click on the button succeeded ('ok' in log from onSuccessHandler), but textbox value didn't change, need another refresh of page to have datasource re-loaded to see the new value. That is not what binding explained by Google's document "any change to a name on the server automatically updates the text displayed in the text box".
A screenshot for info
I expect that two-way binding works as google's statement, and my server codes update can lead to an automatic UI value change. As I didn't see this happening, I have to manually re-load datasource, I hope this is not necessary and want to know how to have this server triggered binding value update works, any thought or suggestion is appreciated.
UPDATE:
I did an additional test and have more finding: server side data update can be see automatically on client side when:
record.TotalPrice = record.UnitPrice * record.Quantity;
var doublePrice = record.TotalPrice * 2;
var recordD = record.double;
recordD.doubleSum = doublePrice;
app.saveRecords([record,recordD]);
Once an update on UnitPrice or Quantity, modelA's TotalPrice and modelB's doubleSum value updated by Server Script, while modelA's TotalPrice updated on UI automatically, modelB's doubleSum requires a page/datasource reload to update on UI.
It looks that Appmaker only keep current item's own data (not relation model's) synchronised between client UI and server in real time. IOW, only SIMPLE binding can see two-way binding in case an update triggered by a change on current item's value from client side.
Upvotes: 1
Views: 100
Reputation: 5253
The concept of two way binding is misleading. In your example for the client change, that's the two way binding. Let me explain in detail...
In the table, item number one has the email [email protected]. That email value is shown by a Label widget that is binded to the email field on the server. When you click the CHANGE_CLIENT button, you change the information on the client first. That's why the Label widget that is on the table row get's updated, then it updates on the server. That is what is meant by
Additionally, any change to a name on the server automatically updates the text displayed in the text box.
That is because it gives the effect that it changed on the server and afterwards on the client. In other words, the text box that you are using to put the new value, does not uses binding, hence you need to use client script to update the value on the client which then triggers an event to update the value on the server.
Now, when you perform the change using server script, the data in the client never updates because the record needs to reload. For that your script should look like this:
function c(newvalue) {
google.script.run.withSuccessHandler(function(){
console.log('ok');
app.datasources.TheDatasource.item._reload();
}).withFailureHandler(function(err){
console.log(err);
}).change(newvalue);
}
In reality, the two way binding only refers to changes that happen in the client and reflects on the server. I believe the documentation wording should change to avoid confusion.
Upvotes: 2