如何有效地重置绑定控制值



我有"添加新…"带有多个sap.m.Input字段的屏幕。一切都在起作用。我提交表格,值存储在数据库中。但是,一旦我重新打开了"添加新的……"……屏幕,我获得了具有先前输入值的表单。

目前,我可以通过sap.ui.core.Element在所有sap.m.Input字段上解决问题,重置值:

Element.registry.forEach(el => {
    if (el.isA("sap.m.Input") && el.sId.includes(inputFieldsMask)) {
        sap.ui.getCore().byId(el.sId).setValue("");
    }
});

其中inputFieldsMask是相关屏幕所有输入字段的掩码。

据我了解,Element.registry.forEach在应用程序中的所有控件上迭代,因此,我不确定从性能的角度来看,这是清理字段的最佳方法。

是否有更好的方法从先前输入的值重置输入字段?

有几种方法可以根据创建新条目采用哪种方法来重置控制值。例如,在目标容器定义(例如包含sap.m.Dialog的片段(中给出了相对绑定

  1. 通过targetContainer.setBindingContext传递Context实例,或者,如果可能的话,让该框架创建并通过targetContainer.bindElement/.bindObject设置一个。这可以解决上下文可以解决的所有相对绑定(如果各自的路径有效(,并允许通过双向绑定直接操纵UI的界数据。
  2. <用户输入一些数据并提交...>
  3. 成功提交编辑后,请致电targetContainer.unbindElement/.unbindObject

通过解开元素,该框架清理了目标容器的内部元素绑定信息,并重置给定模型的所有相对控制值。

请记住,API unbindElement/unbindObject等待可能需要的模型名称。

示例(客户端模型(:

globalThis.onUI5Init = () => sap.ui.require([
  "sap/ui/core/mvc/Controller",
  "sap/ui/core/mvc/XMLView",
  "sap/ui/model/json/JSONModel", // Sample model for the sake of this demo
  "sap/ui/core/Core",
], async (Controller, XMLView, JSONModel, Core) => {
  "use strict";
  
  const MyController = Controller.extend("demo.MyController", {
    handleAddPress: function() {
      const dialog = this.byId("myDialog");
      const clientListBinding = this.byId("myList").getBinding("items");
      // In case of OData and if no context exists yet, consider creating a new context via odataListBinding.create, v4.ODataModel#getKeepAliveContext, etc.
      clientListBinding.suspend(); // to update the list once the dialog closes
      this._currentItems = this.getView().getModel().getProperty("/myItems"); // for the cancel case (onESCPress)
      dialog.getModel().setProperty("/myItems", this._currentItems.concat({})); // new empty item. Applies only to this client-side model
      dialog.bindElement(`/myItems/${/*index:*/clientListBinding.getLength()}`); // or setBindingContext
      dialog.open();
    },
    onESCPress: function(promise) {
      if (this._isStillRequesting) {
        return promise.reject();
      }
      const model = this.getView().getModel();
      model.setProperty("/myItems", this._currentItems);
      return promise.resolve(); // continue closing the dialog
    },
    
    onAfterClose: function(event) {
      this.handleAfterClose(event.getSource(), this.byId("myList").getBinding("items"));
    },
    
    handleAfterClose: function(dialog, listBinding) {
      dialog.unbindElement(/*modelName*/); // <-- resets the data in dialog and cleans up its element binding infos internally. No dialog.destory needed.
      dialog.setBusy(false);
      listBinding.resume();
    },
    
    handleSubmit: function() {
      const dialog = this.byId("myDialog");
      if (!dialog.getBeginButton().getEnabled()) return;
      dialog.setBusy(true);
      if (!this._isStillRequesting) {
        this._isStillRequesting = true;
        /*Faking request:*/setTimeout(this.mySuccessHandler.bind(this), 3000)
      };
    },
    
    mySuccessHandler: function (newKeyFromServer = globalThis.crypto.randomUUID()) {
      const dialog = this.byId("myDialog");
      const context = dialog.getBindingContext();
      const value = context.getProperty("value");
      this._isStillRequesting = false;
      dialog.getModel().setProperty(context.getPath("key"), newKeyFromServer);
      dialog.close();
      sap.ui.require([ "sap/m/MessageToast" ], MT => MT.show(`${value} created`));
    },
  });
  const control = await XMLView.create({
    definition: document.getElementById("myxmlview").textContent,
    height: "100%",
    controller: new MyController(),
    models: {
      undefined: new JSONModel({
        "myItems": [],
      }),
      "messages": Core.getMessageManager().getMessageModel(),
    },
  });
  Core.getMessageManager().registerObject(control.placeAt("content"), true);
});
<script id="sap-ui-bootstrap" src="https://sdk.openui5.org/nightly/resources/sap-ui-core.js"
  data-sap-ui-oninit="onUI5Init"
  data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.layout,sap.ui.unified"
  data-sap-ui-theme="sap_horizon"
  data-sap-ui-async="true"
  data-sap-ui-compatversion="edge"
  data-sap-ui-excludejquerycompat="true"
  data-sap-ui-resourceroots='{ "demo": "./" }'
  data-sap-ui-xx-waitForTheme="init"
></script>
<script id="myxmlview" type="text/xml">
  <mvc:View xmlns:mvc="sap.ui.core.mvc" height="100%" controllerName="demo.MyController">
    <App xmlns="sap.m">
      <Page backgroundDesign="List" title="Resetting inputs via client-side Model and Context">
        <headerContent>
          <Button id="addBtn" text="Add Item" type="Emphasized" press=".handleAddPress" />
        </headerContent>
        <List id="myList" growing="true" items="{
          path: '/myItems',
          key: 'key',
          templateShareable: false
        }">
          <StandardListItem title="{value}" info="Key: {key}"/>
        </List>
      </Page>
      <dependents>
        <Dialog id="myDialog"
          icon="sap-icon://ui-notifications"
          title="New Item"
          draggable="true"
          initialFocus="myInput"
          class="sapUiResponsiveContentPadding"
          escapeHandler=".onESCPress"
          afterClose=".onAfterClose"
        >
          <Input id="myInput"
            placeholder="&lt;New value>"
            valueLiveUpdate="true"
            value="{
              path: 'value',
              type: 'sap.ui.model.type.String',
              constraints: {
                minLength: 1
              }
            }"
            submit=".handleSubmit"
          />
          <beginButton>
            <Button
              text="Submit"
              type="Emphasized"
              enabled="{= !!%{value} &amp;&amp; !%{messages>/}.length}"
              press=".handleSubmit"
            />
          </beginButton>
        </Dialog>
      </dependents>
    </App>
  </mvc:View>
</script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>

当然,绑定和解开元素也适用于服务器端模型,例如v2.ODataModelv4.ODataModel。但是如何根据用例创建或访问v2.Context/v4.Context的实例。请参阅各个模型,上下文,ODataListBindingODataContextBinding的文档主题和API参考。

unbindElement/ unbindObject带有相对绑定的好处

  • ✅控制不可思议:无需依靠控制特定的API,例如myInput.setValuemySwitch.setState等。
  • ✅减少过载:无需在所有现有控件上迭代。该框架将负责重置相关的绑定。
  • ✅减少维护:无需维护应用程序应该手动重置的模型属性列表。
  • ✅减少工作量:每次无需致电myDialog.destroy()即可清除用户输入。保持现有的清理控制实例并将其重复使用下一个数据输入。

最佳实践是使用模型存储您的应用程序数据并将任何输入字段绑定到该模型。我在这里添加了一个示例。为了简单起见,按下按钮时清除了模型数据。

在现实世界应用中,您将模型的任何设置都放在onRouteMatched处理程序中,以确保数据处于初始状态。

onRouteMatched : function(event) {
    this.getView().getModel().setData({
        "firstName": "",
        "lastName": ""
    });
}

将所有控制值绑定到模型。然后在成功保存数据后重置此模型。

示例:

control1.bindProperty("value", "/controlValues/control1Value"); // Binding
// control1.bindProperty("value", "/controlValues/name");
// <Input value="{/controlValues/name}" /> // <-- ideal binding in xml view
this.getView().getModel().setProperty("/controlValues", this.resetFormData()); // Clear Model
resetFormData: function () {
    var emptyControlValues = {
        "control1Value": "", // "name": "", <-- bind to control
        "control2Value": 0,  // "age": 0,
        "control3Value": "", // "address": "",
        "control4Value": ""  // "tel": ""
    };
    return emptyControlValues;
};

最新更新