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 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