Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating model in UI5, two-way data binding becomes one-way when using formatter

In my UI5-app, I have a table where each row contains a sap.m.Switch, which is bound to the model via formatter, since the data is coming from the DB as 1/0, rather than true/false, and that, probably, breaks the default two-way data binding.

To update a data model upon the editing value of this switch, I implemented the following change-event:

onChangeSwitch: function onChangeSwitch(oEvent) {
    let context = oEvent.oSource.getBindingContext();
    let itemIndex = context.sPath.substr(1);
    let oModel = this.getView().byId("idTablePersons").getModel();
    oModel.oData[itemIndex].isPersonActive = (oEvent.mParameters.state) ? 1 : 0;
    oModel.refresh();
}

It does work, but I'm not sure if it is a proper way to implement such logic. Is there a standard way to update a model after changing sap.m.Switch value?

like image 323
Mike Avatar asked Jan 26 '23 05:01

Mike


2 Answers

I think you're approaching this the wrong way around. sap.m.Switch already has an attribute to indicate state which you can directly bind to a model.

<Switch state="{IsPersonActive}" />

Assuming you bound the items in the table to an unnamed model, that'll set the IsPersonActive flag on the bound line to true or false depending on the state of the switch.

This also means it'll come out with the switches in the correct state if certain IsPersonActive flags are already set to true or false in your entity sets.


(…) the data is coming from the DB as 1/0, rather than true/false (…).
Is there a standard way to update a model after changing sap.m.Switch value?

The two-way data binding fix from https://embed.plnkr.co/wwQXf8bTuiTP4RlP:

NumericBoolean.js (minimal example):

sap.ui.define([
  "sap/ui/model/SimpleType",
], Type => Type.extend('demo.model.type.NumericBoolean', {
  constructor: function() {
    Type.apply(this, arguments);
  },
  formatValue: iValue => !!+iValue,
  parseValue: bValue => bValue ? 1 : 0,
  validateValue: vValue => { /*validate...*/ },
}));
<Switch xmlns="sap.m" xmlns:core="sap.ui.core"
  core:require="{ NumericBoolean: 'demo/model/type/NumericBoolean' }"
  state="{
    path: '/1or0',
    type: 'NumericBoolean'
  }"
/>

Important note:
It's mandatory to keep the validateValue declaration even if the implementation is not provided, otherwise sap.m.Switch will not work correctly.

like image 198
Jorg Avatar answered Apr 29 '23 19:04

Jorg


Instead of the formatter, use expression binding wherever possible, i.e. for switch attribute „state“ to map 0/1 to true/false. https://sapui5.hana.ondemand.com/1.34.9/docs/guide/daf6852a04b44d118963968a1239d2c0.html

But overall, I suggest to use a custom type (see above), as the same is the two-way binding solution without the need of an implemented change-event.

like image 41
Michael Biermann Avatar answered Apr 29 '23 19:04

Michael Biermann