1# Updating Widget Content by State 2 3 4Multiple widgets of the same application can be configured to implement different features. For example, two weather widgets can be added to the home screen: one for displaying the weather of London, and the other Beijing. The widget is set to be updated at 07:00 every morning. It needs to detect the configured city, and then updates the city-specific weather information. The following example describes how to dynamically update the widget content based on the state. 5 6 7- Widget configuration file: Configure the widget to be updated at 07:00 every morning. 8 9 ```json 10 { 11 "forms": [ 12 { 13 "name": "widget", 14 "description": "This is a service widget.", 15 "src": "./ets/widget/pages/WidgetCard.ets", 16 "uiSyntax": "arkts", 17 "window": { 18 "designWidth": 720, 19 "autoDesignWidth": true 20 }, 21 "colorMode": "auto", 22 "isDefault": true, 23 "updateEnabled": true,"scheduledUpdateTime": "07:00", 24 "updateDuration": 0, 25 "defaultDimension": "2*2", 26 "supportDimensions": ["2*2"] 27 } 28 ] 29 } 30 ``` 31 32- Widget page: A widget has different states and needs to be updated by state. When the state changes, **postCardAction** is called to notify the EntryFormAbility. 33 34 ```ts 35 let storage = new LocalStorage(); 36 @Entry(storage) 37 @Component 38 struct WidgetCard { 39 @LocalStorageProp('textA') textA: string = 'To be updated...'; 40 @LocalStorageProp('textB') textB: string ='To be updated...'; 41 @State selectA: boolean = false; 42 @State selectB: boolean = false; 43 44 build() { 45 Column() { 46 Row() { 47 Checkbox({ name: 'checkbox1', group: 'checkboxGroup' }) 48 .select(false) 49 .onChange((value: boolean) => { 50 this.selectA = value; 51 postCardAction(this, { 52 'action': 'message', 53 'params': { 54 'selectA': JSON.stringify(value) 55 } 56 }); 57 }) 58 Text ('State A') 59 } 60 61 Row() { 62 Checkbox({ name: 'checkbox2', group: 'checkboxGroup' }) 63 .select(false) 64 .onChange((value: boolean) => { 65 this.selectB = value; 66 postCardAction(this, { 67 'action': 'message', 68 'params': { 69 'selectB': JSON.stringify(value) 70 } 71 }); 72 }) 73 Text ('State B') 74 } 75 76 Row() {// Content that is updated only in state A 77 Text('State A: ') 78 Text(this.textA) 79 } 80 81 Row() { // Content that is updated only in state B 82 Text ('State B:') 83 Text(this.textB) 84 } 85 }.padding('10%') 86 } 87 } 88 ``` 89 90- EntryFormAbility: The widget state data is stored in the local database. When the update event callback is triggered, the current widget state is obtained through **formId**, and then content is updated based on the state obtained. 91 92 ```ts 93 import formInfo from '@ohos.app.form.formInfo' 94 import formProvider from '@ohos.app.form.formProvider'; 95 import formBindingData from '@ohos.app.form.formBindingData'; 96 import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; 97 import dataStorage from '@ohos.data.storage' 98 99 export default class EntryFormAbility extends FormExtensionAbility { 100 onAddForm(want) { 101 let formId = want.parameters[formInfo.FormParam.IDENTITY_KEY]; 102 let isTempCard: boolean = want.parameters[formInfo.FormParam.TEMPORARY_KEY]; 103 if (isTempCard === false) {// If the widget is a normal one, the widget information is persisted. 104 console.info('Not temp card, init db for:' + formId); 105 let storeDB = dataStorage.getStorageSync(this.context.filesDir + 'myStore') 106 storeDB.putSync('A' + formId, 'false'); 107 storeDB.putSync('B' + formId, 'false'); 108 storeDB.flushSync(); 109 } 110 let formData = {}; 111 return formBindingData.createFormBindingData(formData); 112 } 113 114 onRemoveForm(formId) { 115 console.info('onRemoveForm, formId:' + formId); 116 let storeDB = dataStorage.getStorageSync(this.context.filesDir + 'myStore') 117 storeDB.deleteSync('A' + formId); 118 storeDB.deleteSync('B' + formId); 119 } 120 121 // If the widget is a temporary one, it is recommended that the widget information be persisted when the widget is converted to a normal one. 122 onCastToNormalForm(formId) { 123 console.info('onCastToNormalForm, formId:' + formId); 124 let storeDB = dataStorage.getStorageSync(this.context.filesDir + 'myStore') 125 storeDB.putSync('A' + formId, 'false'); 126 storeDB.putSync('B' + formId, 'false'); 127 storeDB.flushSync(); 128 } 129 130 onUpdateForm(formId) { 131 let storeDB = dataStorage.getStorageSync(this.context.filesDir + 'myStore') 132 let stateA = storeDB.getSync('A' + formId, 'false').toString() 133 let stateB = storeDB.getSync('B' + formId, 'false').toString() 134 // Update textA in state A. 135 if (stateA === 'true') { 136 let formInfo = formBindingData.createFormBindingData({ 137 'textA': 'AAA' 138 }) 139 formProvider.updateForm(formId, formInfo) 140 } 141 // Update textB in state B. 142 if (stateB === 'true') { 143 let formInfo = formBindingData.createFormBindingData({ 144 'textB': 'BBB' 145 }) 146 formProvider.updateForm(formId, formInfo) 147 } 148 } 149 150 onFormEvent(formId, message) { 151 // Store the widget state. 152 console.info('onFormEvent formId:' + formId + 'msg:' + message); 153 let storeDB = dataStorage.getStorageSync(this.context.filesDir + 'myStore') 154 let msg = JSON.parse(message) 155 if (msg.selectA != undefined) { 156 console.info('onFormEvent selectA info:' + msg.selectA); 157 storeDB.putSync('A' + formId, msg.selectA); 158 } 159 if (msg.selectB != undefined) { 160 console.info('onFormEvent selectB info:' + msg.selectB); 161 storeDB.putSync('B' + formId, msg.selectB); 162 } 163 storeDB.flushSync(); 164 } 165 }; 166 ``` 167 168 169> **NOTE** 170> When the local database is used for widget information persistence, it is recommended that [TEMPORARY_KEY](../reference/apis/js-apis-app-form-formInfo.md#formparam) be used to determine whether the currently added widget is a normal one in the [onAddForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#onaddform) lifecycle callback. If the widget is a normal one, the widget information is directly persisted. If the widget is a temporary one, the widget information is persisted when the widget is converted to a normal one ([onCastToNormalForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#oncasttonormalform)). In addition, the persistent widget information needs to be deleted when the widget is destroyed ([onRemoveForm](../reference/apis/js-apis-app-form-formExtensionAbility.md#onremoveform)), preventing the database size from continuously increasing due to repeated widget addition and deletion. 171