1# ArkUI Subsystem Changelog
2
3
4## cl.arkui.1 Reporting of Unexpected Number of @Extend/@AnimatableExtend Parameters
5
6The @Extend and @AnimatableExtend decorators allow for only one parameter.
7
8**Change Impact**
9
10When there are multiple parameters for the @Extend/@AnimatableExtend decorator, a compilation error is reported.
11
12**Example (incorrect)**:
13
14```ts
15// xxx.ets
16
17@Extend(Text, Button)  // Compilation error: @Extend should have one and only one parameter.
18function fancy() {
19  .width(100)
20}
21
22@AnimatableExtend(Text, Polyline)  //Compilation error: @AnimatableExtend should have one and only one parameter.
23function fancy2() {
24  .height(100)
25}
26
27@Entry
28@Component
29struct Example {
30  build() {
31    Column() {
32      Text('text')
33        .fancy()
34        .fancy2()
35    }
36  }
37}
38```
39
40**Key API/Component Changes**
41
42N/A
43
44**Adaptation Guide**
45
46Make sure the @Extend and @AnimatableExtend decorators contain only one parameter.
47
48The code snippet is as follows:
49```ts
50// xxx.ets
51
52@Extend(Text)
53function fancy() {
54  .width(100)
55}
56
57@AnimatableExtend(Text)
58function fancy2() {
59  .height(100)
60}
61
62@Entry
63@Component
64struct Example {
65  build() {
66    Column() {
67      Text('text')
68        .fancy()
69        .fancy2()
70    }
71  }
72}
73```
74
75## cl.arkui.2 Reporting of @Link/@ObjectLink Member Variables Not Being Configured from Parent Components
76
77The value of an @Link or @ObjectLink decorated member variable in a component must be from the parent component.
78
79**Change Impact**
80
81When the value of an @Link/@ObjectLink decorated member variable in a component is not configured from the parent component, a compilation error is reported.
82
83**Example (incorrect)**:
84
85```ts
86// xxx.ets
87
88@Observed
89class Count {
90  message: string = 'count'
91}
92
93@Entry
94@Component
95struct Parent {
96  @State state1: string = 'state1';
97  @State state2: Count = new Count();
98  build() {
99    Column() {
100      Child()  // Compilation error: Property 'link' in the custom component 'Child' is missing (mandatory to specify).
101               // Compilation error: Property 'objectLink' in the custom component 'Child' is missing (mandatory to specify).
102    }
103  }
104}
105
106@Component
107struct Child {
108  @Link link: string;
109  @ObjectLink objectLink: Count;
110  build() {
111    Column() {
112      Text(this.link)
113        .fontSize(50)
114      Text(this.objectLink.message)
115        .fontSize(50)
116    }
117  }
118}
119```
120
121**Key API/Component Changes**
122
123N/A
124
125**Adaptation Guide**
126
127Configure the @Link and @ObjectLink decorated member variables in components to get their values from the parent component.
128
129The code snippet is as follows:
130```ts
131// xxx.ets
132
133@Observed
134class Count {
135  message: string = 'count'
136}
137
138@Entry
139@Component
140struct Parent {
141  @State state1: string = 'state1';
142  @State state2: Count = new Count();
143  build() {
144    Column() {
145      Child({link: $state1, objectLink: this.state2})
146    }
147  }
148}
149
150@Component
151struct Child {
152  @Link link: string;
153  @ObjectLink objectLink: Count;
154  build() {
155    Column() {
156      Text(this.link)
157        .fontSize(50)
158      Text(this.objectLink.message)
159        .fontSize(50)
160    }
161  }
162}
163```
164## cl.arkui.3 Behavior Change of the onReady Event for \<Canvas>
165
166**Description**
167The **onReady** event is triggered when the component is ready or when the component size changes. After it is triggered, the canvas is cleared.
168
169**Example**
170```ts
171@Entry
172@Component
173struct OnReadyDiff {
174  @State message: string = 'init '
175  @State isShow: boolean = false
176  @State myHeight: number = 300
177  private settings: RenderingContextSettings = new RenderingContextSettings(true);
178  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
179
180  build() {
181    Row() {
182      Column() {
183        Text(this.message)
184          .fontSize(50)
185          .fontWeight(FontWeight.Bold)
186        Button('ChangePosition')
187          .onClick(()=>{
188            this.isShow = !this.isShow
189          })
190        if (this.isShow) {
191          Button('new button')
192            .height(200)
193        }
194        Button('ChangeHeight')
195          .onClick(()=>{
196            this.myHeight = this.myHeight==300?500:300
197          })
198
199        Canvas(this.context)
200          .width(300)
201          .height(this.myHeight)
202          .backgroundColor('#ffff00')
203          .onReady(() =>{
204            this.context.fillRect(0, 0, 100, 100)
205            this.message += 'a '
206          })
207        Button('draw another')
208          .onClick(()=>{
209            this.context.fillRect(100, 100, 100, 100)
210          })
211      }
212      .width('100%')
213    }
214    .height('100%')
215  }
216}
217```
218
219API version 9: The **onReady** event is triggered when the component is ready, when the component location changes, or when the component size changes.
220
221![stack](figures/api9onReady.gif)
222
223API version 10 and later: The **onReady** event is triggered when the component is ready or when the component size changes. It is not triggered when the component location changes.
224
225![stack](figures/api10onReady.gif)
226
227**Change Impact**
228
229When the component location changes, the **onReady** event is triggered in API version 9 and earlier versions, but not in API version 10 and later versions.
230
231## cl.arkui.4 Change of How Percentage Is Calculated for Margin
232
233Before the change: The margin is calculated twice when set in percentage. The second calculation is conducted after the result of the first calculation has been subtracted from the percentage reference. After the change: The first margin calculation result is used as the final result, and the second calculation is not conducted.
234
235**Change Impact**
236
237This change affects calculation of margins set in percentage.
238
239**Example (incorrect)**:
240
241```ts
242// xxx.ets
243@Entry
244@Component
245struct TextInputExample {
246  @State text: string = ''
247  controller: TextInputController = new TextInputController()
248
249  build() {
250    Column(){
251      Row().margin({left:"50%"}).width(100).height(100)
252    }.width("100%").height("100%")
253  }
254}
255```
256
257**Key API/Component Changes**
258
259N/A
260
261**Adaptation Guide**
262
263After the change, the margin percentage reference is fixed at the parent component's width minus its padding, and does not subtract the result of the first margin calculation. As a result, the margin percentage is slightly greater than that before the change. Account for this change when setting the margin percentage.
264
265## cl.arkui.5 Change of SwipeActionItem in the \<ListItem> Component
266
267Changed **Delete** in the parameters of the **SwipeActionItem** API of the **\<ListItem>** component to **Action**, and deleted the **useDefaultDeleteAnimation** API.
268
269**Change Impact**
270
271When developing an application based on OpenHarmony 4.0.9.3 or a later SDK version, you need to use the new APIs.
272
273**Key API/Component Changes**
274
275| API Before Change    |  API After Change    |
276| ------ | ------------------------------ |
277| deleteAreaDistance   | actionAreaDistance |
278| onDelete   |  onAction |
279| onEnterDeleteArea   | onEnterActionArea |
280| onExitDeleteArea   | onExitActionArea |
281| useDefaultDeleteAnimation | Deleted|
282
283**Adaptation Guide**
284
285When developing an application based on OpenHarmony 4.0.9.3 or a later SDK version, use the new APIs of **SwipeActionItem**. When developing an application based on OpenHarmony 4.0.9.2 or an earlier SDK version, use the original APIs of **SwipeActionItem**.
286
287The code snippet is as follows:
288
289```ts
290// xxx.ets
291@Entry
292@Component
293struct ListItemExample2 {
294  @State message: string = 'Hello World'
295  @State arr: number[] = [0, 1, 2, 3, 4]
296  @State enterEndDeleteAreaString: string = "not enterEndDeleteArea"
297  @State exitEndDeleteAreaString: string = "not exitEndDeleteArea"
298
299  @Builder itemEnd() {
300    Row() {
301      Button("Delete").margin("4vp")
302      Button("Set").margin("4vp")
303    }.padding("4vp").justifyContent(FlexAlign.SpaceEvenly)
304  }
305
306  build() {
307    Column() {
308      List({ space: 10 }) {
309        ForEach(this.arr, (item) => {
310          ListItem() {
311            Text("item" + item)
312              .width('100%')
313              .height(100)
314              .fontSize(16)
315              .textAlign(TextAlign.Center)
316              .borderRadius(10)
317              .backgroundColor(0xFFFFFF)
318          }
319          .transition({ type: TransitionType.Delete, opacity: 0 })
320          .swipeAction({
321            end: {
322              builder: this.itemEnd.bind(this, item),
323              onAction: () => {
324                animateTo({ duration: 1000 }, () => {
325                  let index = this.arr.indexOf(item)
326                  this.arr.splice(index, 1)
327                })
328              },
329              actionAreaDistance: 80,
330              onEnterActionArea: () => {
331                this.enterEndDeleteAreaString = "enterEndDeleteArea"
332                this.exitEndDeleteAreaString = "not exitEndDeleteArea"
333              },
334              onExitActionArea: () => {
335                this.enterEndDeleteAreaString = "not enterEndDeleteArea"
336                this.exitEndDeleteAreaString = "exitEndDeleteArea"
337              }
338            }
339          })
340        }, item => item)
341      }
342      Text(this.enterEndDeleteAreaString).fontSize(20)
343      Text(this.exitEndDeleteAreaString).fontSize(20)
344    }
345    .padding(10)
346    .backgroundColor(0xDCDCDC)
347    .width('100%')
348    .height('100%')
349  }
350}
351```
352