1e41f4b71Sopenharmony_ci# Updating Widget Content Through a Proxy
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciA widget can be updated through a proxy – a system application that has data sharing enabled – when the widget provider is not running.
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci## Implementation Principles
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci**Figure 1** Updating widget content through a proxy
8e41f4b71Sopenharmony_ci![UpdateWidgetByProxyPrinciple](figures/UpdateWidgetByProxyPrinciple.png)
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ciCompared with the [implementation of the ArkTS widget](arkts-ui-widget-working-principles.md#implementation-principles) alone, updating through a proxy involves the data management service and data provider.
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci- Data management service: provides a mechanism for data sharing among multiple applications.
13e41f4b71Sopenharmony_ci- Data provider: must be a system application that has data sharing enabled. The shared data is identified through the defined **key** + **subscriberId** combination.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci> **NOTE**
16e41f4b71Sopenharmony_ci>
17e41f4b71Sopenharmony_ci> This feature can be used when the system provides applications as data providers and publicly available shared data identifiers.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ciProcessing flow of the widget provider (indicated by the blue arrows in the figure):
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci1. The widget provider sets the **dataProxyEnabled** field to **true** in the **form_config.json** file to enable the update-through-proxy feature.
22e41f4b71Sopenharmony_ci> **NOTE**
23e41f4b71Sopenharmony_ci>
24e41f4b71Sopenharmony_ci> After the update-through-proxy feature is enabled, the settings for [updating periodically](arkts-ui-widget-update-by-time.md) do not work.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci2. In the [onAddForm](../reference/apis-form-kit/js-apis-app-form-formExtensionAbility.md#onaddform) callback, the widget provider returns the **key** + **subscriberId** combination defined by the data provider to the Widget Manager.
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci3. The Widget Manager parses the subscription information of the widget provider and registers a subscription instance with the data management service.
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ciProcessing flow of the widget update proxy (indicated by the red arrows in the figure):
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci1. The data provider uses the **key** + **subscriberId** combination as the data ID to store data to the database.
33e41f4b71Sopenharmony_ci2. The data management service detects the change in the database and publishes the new data to all currently registered subscription instances.
34e41f4b71Sopenharmony_ci3. The Widget Manager parses data from the subscription instance and sends the data to the widget rendering service.
35e41f4b71Sopenharmony_ci4. The widget rendering service runs the widget page code **widgets.abc**, which implements rendering based on the new data and sends the rendered data to the <!--Del-->[<!--DelEnd-->FormComponent<!--Del-->](../reference/apis-arkui/arkui-ts/ts-basic-components-formcomponent-sys.md)<!--DelEnd--> corresponding to the widget host.
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ciThere are two types of shared data provided by the data provider:
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci- Ephemeral data: data that exists only for a specific period of time and can be subscribed to by system and non-system applications alike.
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci- Persistent data: data that persists over time and can only be subscribed to by system applications.
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ciThe update-through-proxy configuration varies by the type of shared data.
44e41f4b71Sopenharmony_ci<!--Del-->
45e41f4b71Sopenharmony_ci## Data Provider Development
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ciFor details, see [Data Management](../database/share-data-by-silent-access.md).
48e41f4b71Sopenharmony_ci<!--DelEnd-->
49e41f4b71Sopenharmony_ci## Widget Provider Development (Ephemeral Data)
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci- Set the **dataProxyEnabled** field to **true** in the **form_config.json** file to enable the update-through-proxy feature.
52e41f4b71Sopenharmony_ci  ```json
53e41f4b71Sopenharmony_ci  {
54e41f4b71Sopenharmony_ci    "forms": [
55e41f4b71Sopenharmony_ci      {
56e41f4b71Sopenharmony_ci        "name": "WidgetProcessData",
57e41f4b71Sopenharmony_ci        "description": "$string:ProcessDataEntryAbility_desc",
58e41f4b71Sopenharmony_ci        "src": "./ets/widgetprocessdata/pages/WidgetProcessDataCard.ets",
59e41f4b71Sopenharmony_ci        "uiSyntax": "arkts",
60e41f4b71Sopenharmony_ci        "window": {
61e41f4b71Sopenharmony_ci          "designWidth": 720,
62e41f4b71Sopenharmony_ci          "autoDesignWidth": true
63e41f4b71Sopenharmony_ci        },
64e41f4b71Sopenharmony_ci        "colorMode": "auto",
65e41f4b71Sopenharmony_ci        "isDefault": true,
66e41f4b71Sopenharmony_ci        "updateEnabled": true,
67e41f4b71Sopenharmony_ci        "scheduledUpdateTime": "10:30",
68e41f4b71Sopenharmony_ci        "defaultDimension": "2*2",
69e41f4b71Sopenharmony_ci        "supportDimensions": [
70e41f4b71Sopenharmony_ci          "2*2"
71e41f4b71Sopenharmony_ci        ],
72e41f4b71Sopenharmony_ci        "dataProxyEnabled": true
73e41f4b71Sopenharmony_ci      }
74e41f4b71Sopenharmony_ci    ]
75e41f4b71Sopenharmony_ci  }
76e41f4b71Sopenharmony_ci  ```
77e41f4b71Sopenharmony_ci  
78e41f4b71Sopenharmony_ci- Configure the subscription information [proxyData](../reference/apis-form-kit/js-apis-app-form-formBindingData.md#proxydata10) in the [onAddForm](../reference/apis-form-kit/js-apis-app-form-formExtensionAbility.md#onaddform) callback and return the information to the Widget Manager through [formBinding](../reference/apis-form-kit/js-apis-app-form-formBindingData.md#formbindingdata). In this example, **key** is set to **datashareproxy://com.samples.widgetupdatebyproxy/weather** and **subscriberId** is set to **11**.
79e41f4b71Sopenharmony_ci  > **NOTE**
80e41f4b71Sopenharmony_ci  >
81e41f4b71Sopenharmony_ci  > The value of **key** can be a URI or a simple string. The default value of **subscriberId** is the value of **formId**. The actual value depends on the definition of the data provider.
82e41f4b71Sopenharmony_ci  ```ts
83e41f4b71Sopenharmony_ci  import { formBindingData, FormExtensionAbility } from '@kit.FormKit';
84e41f4b71Sopenharmony_ci  import { Want } from '@kit.AbilityKit';
85e41f4b71Sopenharmony_ci  import { hilog } from '@kit.PerformanceAnalysisKit';
86e41f4b71Sopenharmony_ci  
87e41f4b71Sopenharmony_ci  const TAG: string = 'ProcessDataFormAbility';
88e41f4b71Sopenharmony_ci  const DOMAIN_NUMBER: number = 0xFF00;
89e41f4b71Sopenharmony_ci  
90e41f4b71Sopenharmony_ci  export default class ProcessDataFormAbility extends FormExtensionAbility {
91e41f4b71Sopenharmony_ci    onAddForm(want: Want): formBindingData.FormBindingData {
92e41f4b71Sopenharmony_ci      let formData: Record<string, Object> = {};
93e41f4b71Sopenharmony_ci      let proxies: formBindingData.ProxyData[] = [
94e41f4b71Sopenharmony_ci        {
95e41f4b71Sopenharmony_ci          key: 'datashareproxy://com.samples.widgetupdatebyproxy/weather',
96e41f4b71Sopenharmony_ci          subscriberId: '11'
97e41f4b71Sopenharmony_ci        }
98e41f4b71Sopenharmony_ci      ];
99e41f4b71Sopenharmony_ci      let formBinding = formBindingData.createFormBindingData(formData);
100e41f4b71Sopenharmony_ci      formBinding.proxies = proxies;
101e41f4b71Sopenharmony_ci      hilog.info(DOMAIN_NUMBER, TAG, 'onAddForm');
102e41f4b71Sopenharmony_ci      return formBinding;
103e41f4b71Sopenharmony_ci    }
104e41f4b71Sopenharmony_ci  }
105e41f4b71Sopenharmony_ci  ```
106e41f4b71Sopenharmony_ci  
107e41f4b71Sopenharmony_ci- In the [widget page code file](arkts-ui-widget-creation.md), use the variable in LocalStorage to obtain the subscribed data. The variable in LocalStorage is bound to a string and updates the subscribed data in the key:value pair format. The key must be the same as that subscribed to by the widget provider. In this example, the subscribed data is obtained through **'city'** and displayed in the **\<Text>** component.
108e41f4b71Sopenharmony_ci  ```ts
109e41f4b71Sopenharmony_ci  let storageProcess = new LocalStorage();
110e41f4b71Sopenharmony_ci  
111e41f4b71Sopenharmony_ci  @Entry(storageProcess)
112e41f4b71Sopenharmony_ci  @Component
113e41f4b71Sopenharmony_ci  struct WidgetProcessDataCard {
114e41f4b71Sopenharmony_ci    @LocalStorageProp('datashareproxy://com.samples.widgetupdatebyproxy/weather') city: ResourceStr = $r('app.string.loading');
115e41f4b71Sopenharmony_ci  
116e41f4b71Sopenharmony_ci    build() {
117e41f4b71Sopenharmony_ci      Column() {
118e41f4b71Sopenharmony_ci        Column() {
119e41f4b71Sopenharmony_ci          Text(this.city)
120e41f4b71Sopenharmony_ci            .fontColor('#FFFFFF')
121e41f4b71Sopenharmony_ci            .opacity(0.9)
122e41f4b71Sopenharmony_ci            .fontSize(14)
123e41f4b71Sopenharmony_ci            .margin({ top: '8%', left: '10%' })
124e41f4b71Sopenharmony_ci        }.width('100%')
125e41f4b71Sopenharmony_ci        .alignItems(HorizontalAlign.Start)
126e41f4b71Sopenharmony_ci      }.width('100%').height('100%')
127e41f4b71Sopenharmony_ci      .backgroundImage($r('app.media.CardEvent'))
128e41f4b71Sopenharmony_ci      .backgroundImageSize(ImageSize.Cover)
129e41f4b71Sopenharmony_ci    }
130e41f4b71Sopenharmony_ci  }
131e41f4b71Sopenharmony_ci  ```
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci## Widget Provider Development (Persistent Data; for System Applications Only)
134e41f4b71Sopenharmony_ci- Set the **dataProxyEnabled** field to **true** in the **form_config.json** file to enable the update-through-proxy feature.
135e41f4b71Sopenharmony_ci  ```json
136e41f4b71Sopenharmony_ci  {
137e41f4b71Sopenharmony_ci    "forms": [
138e41f4b71Sopenharmony_ci      {
139e41f4b71Sopenharmony_ci        "name": "WidgetPersistentData",
140e41f4b71Sopenharmony_ci        "description": "This is a service widget update by proxy using persistent data.",
141e41f4b71Sopenharmony_ci        "src": "./ets/widgetpersistentdata/pages/WidgetPersistentDataCard.ets",
142e41f4b71Sopenharmony_ci        "uiSyntax": "arkts",
143e41f4b71Sopenharmony_ci        "window": {
144e41f4b71Sopenharmony_ci          "designWidth": 720,
145e41f4b71Sopenharmony_ci          "autoDesignWidth": true
146e41f4b71Sopenharmony_ci        },
147e41f4b71Sopenharmony_ci        "colorMode": "auto",
148e41f4b71Sopenharmony_ci        "isDefault": true,
149e41f4b71Sopenharmony_ci        "updateEnabled": true,
150e41f4b71Sopenharmony_ci        "scheduledUpdateTime": "10:30",
151e41f4b71Sopenharmony_ci        "updateDuration": 1,
152e41f4b71Sopenharmony_ci        "defaultDimension": "2*2",
153e41f4b71Sopenharmony_ci        "supportDimensions": [
154e41f4b71Sopenharmony_ci          "2*2"
155e41f4b71Sopenharmony_ci        ],
156e41f4b71Sopenharmony_ci        "dataProxyEnabled": true
157e41f4b71Sopenharmony_ci      }
158e41f4b71Sopenharmony_ci  ]
159e41f4b71Sopenharmony_ci  }
160e41f4b71Sopenharmony_ci  ```
161e41f4b71Sopenharmony_ci
162e41f4b71Sopenharmony_ci- Add a subscription template <!--Del-->[<!--DelEnd-->addTemplate<!--Del-->](../reference/apis-arkdata/js-apis-data-dataShare-sys.md#addtemplate10)<!--DelEnd--> to the [onAddForm](../reference/apis-form-kit/js-apis-app-form-formExtensionAbility.md#onaddform) callback and use the template predicates to notify the database of the subscribed data conditions. Then, configure the subscription information [proxyData](../reference/apis-form-kit/js-apis-app-form-formBindingData.md#proxydata10) and return it to the Widget Manager through [formBinding](../reference/apis-form-kit/js-apis-app-form-formBindingData.md#formbindingdata). In the example, the predicate is set to **"list": "select type from TBL00 limit 0,1"**, indicating that the first data record in the **type** column is obtained from the **TBL00** database. The data is returned to the widget page code file **widgets.abc** in {"list":[{"type":"value0"}]} format. When the subscribed persistent data is updated, the system automatically updates the widget data.
163e41f4b71Sopenharmony_ci
164e41f4b71Sopenharmony_ci  > **NOTE**
165e41f4b71Sopenharmony_ci  >
166e41f4b71Sopenharmony_ci  > - The value of **key** is a URI, which depends on the definition of the data release party.
167e41f4b71Sopenharmony_ci  > - The value of **subscriberId** can be customized. Ensure that the value of **subscriberId** in **addTemplate** is the same as that of **proxies.subscriberId**.
168e41f4b71Sopenharmony_ci  ```ts
169e41f4b71Sopenharmony_ci  import { formBindingData, FormExtensionAbility } from '@kit.FormKit';
170e41f4b71Sopenharmony_ci  import { Want } from '@kit.AbilityKit';
171e41f4b71Sopenharmony_ci  import { dataShare } from '@kit.ArkData';
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci  export default class PersistentDataFormAbility extends FormExtensionAbility {
174e41f4b71Sopenharmony_ci    onAddForm(want: Want): formBindingData.FormBindingData {
175e41f4b71Sopenharmony_ci      let subscriberId = '111';
176e41f4b71Sopenharmony_ci      let template: dataShare.Template = {
177e41f4b71Sopenharmony_ci        predicates: {
178e41f4b71Sopenharmony_ci          'list': `select type from TBL00 where cityId = ${subscriberId}`
179e41f4b71Sopenharmony_ci        },
180e41f4b71Sopenharmony_ci        scheduler: ''
181e41f4b71Sopenharmony_ci      };
182e41f4b71Sopenharmony_ci      dataShare.createDataShareHelper(this.context, 'datashareproxy://com.samples.widgetupdatebyproxy', {
183e41f4b71Sopenharmony_ci        isProxy: true
184e41f4b71Sopenharmony_ci      }).then((data) => {
185e41f4b71Sopenharmony_ci        let dataShareHelper = data;
186e41f4b71Sopenharmony_ci        dataShareHelper.addTemplate('datashareproxy://com.samples.widgetupdatebyproxy/test', subscriberId, template);
187e41f4b71Sopenharmony_ci      });
188e41f4b71Sopenharmony_ci      let formData: Record<string, Object> = {};
189e41f4b71Sopenharmony_ci      let proxies: formBindingData.ProxyData[] = [
190e41f4b71Sopenharmony_ci        {
191e41f4b71Sopenharmony_ci          key: 'datashareproxy://com.samples.widgetupdatebyproxy/test',
192e41f4b71Sopenharmony_ci          subscriberId: subscriberId
193e41f4b71Sopenharmony_ci        }
194e41f4b71Sopenharmony_ci      ];
195e41f4b71Sopenharmony_ci
196e41f4b71Sopenharmony_ci      let formBinding: formBindingData.FormBindingData = {
197e41f4b71Sopenharmony_ci        data: JSON.stringify(formData),
198e41f4b71Sopenharmony_ci        proxies: proxies
199e41f4b71Sopenharmony_ci      };
200e41f4b71Sopenharmony_ci      return formBinding;
201e41f4b71Sopenharmony_ci    }
202e41f4b71Sopenharmony_ci  }
203e41f4b71Sopenharmony_ci  ```
204e41f4b71Sopenharmony_ci
205e41f4b71Sopenharmony_ci- In the [widget page code file](arkts-ui-widget-creation.md), use the variable in LocalStorage to obtain the subscribed data. The variable in LocalStorage is bound to a string and updates the subscribed data in the key:value pair format. The key must be the same as that subscribed to by the widget provider. In the example, the subscribed data is obtained through **'list'**, and the value of the first element is displayed on the **\<Text>** component.
206e41f4b71Sopenharmony_ci  ```ts
207e41f4b71Sopenharmony_ci  let storagePersis = new LocalStorage();
208e41f4b71Sopenharmony_ci  
209e41f4b71Sopenharmony_ci  @Entry(storagePersis)
210e41f4b71Sopenharmony_ci  @Component
211e41f4b71Sopenharmony_ci  struct WidgetPersistentDataCard {
212e41f4b71Sopenharmony_ci    readonly FULL_WIDTH_PERCENT: string = '100%';
213e41f4b71Sopenharmony_ci    readonly FULL_HEIGHT_PERCENT: string = '100%';
214e41f4b71Sopenharmony_ci    @LocalStorageProp('list') list: Record<string, string>[] = [{ 'type': 'a' }];
215e41f4b71Sopenharmony_ci  
216e41f4b71Sopenharmony_ci    build() {
217e41f4b71Sopenharmony_ci      Column() {
218e41f4b71Sopenharmony_ci        Column() {
219e41f4b71Sopenharmony_ci          Text((this.list[0]['type']))
220e41f4b71Sopenharmony_ci            .fontColor('#FFFFFF')
221e41f4b71Sopenharmony_ci            .opacity(0.9)
222e41f4b71Sopenharmony_ci            .fontSize(14)
223e41f4b71Sopenharmony_ci            .margin({ top: '8%', left: '10%' })
224e41f4b71Sopenharmony_ci        }.width('100%')
225e41f4b71Sopenharmony_ci        .alignItems(HorizontalAlign.Start)
226e41f4b71Sopenharmony_ci      }.width(this.FULL_WIDTH_PERCENT).height(this.FULL_HEIGHT_PERCENT)
227e41f4b71Sopenharmony_ci      .backgroundImage($r('app.media.CardEvent'))
228e41f4b71Sopenharmony_ci      .backgroundImageSize(ImageSize.Cover)
229e41f4b71Sopenharmony_ci    }
230e41f4b71Sopenharmony_ci  }
231e41f4b71Sopenharmony_ci  ```
232e41f4b71Sopenharmony_ci
233