1# 如何删除多选框选项 2## 场景说明 3通常情况下,我们使用多选框都会伴随对选项的操作,比较常见的操作是选中后删除,比如删除购物车的商品、删除账单、删除图片等等。但是,当前OpenHarmony针对多选框组件并没有提供直接的删除其选项的方法,需要开发者自己来实现。本例提供了一种实现方案,供开发者参考。 4 5## 效果呈现 6本例最终效果如下: 7 8 9 10 11## 运行环境 12本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 13 14- IDE: DevEco Studio 4.0 Beta1 15- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1) 16 17 18## 实现思路 19本例中涉及的关键特性及实现方案如下: 20- 多选框:使用CheckboxGroup组件构建多选框标题,使用Checkbox组件构建多选框选项。 21- 删除多选框选项:通过CheckboxGroup的onChange回调获取到各个选项的选中状态,在删除操作中,将选中的选项从选项列表中删除。 22- 删除时弹出确认框:使用promptAction模块调用showDialog方法弹出对话框,通过回调获取到用户点击的是取消按钮还是确定按钮,如果是确定按钮则执行删除操作。 23 24## 开发步骤 251. 搭建UI布局。 26 整体纵向布局,那就采用Column组件;全选框用CheckboxGroup组件,然后每个选项都包括一个选择框(Checkbox组件)和一个文本(Text组件),且为横向布局,那我们可以把它们放在Flex组件中;最后是一个Button组件。这样整体布局就有了,具体代码如下: 27 ```ts 28 @Component 29 struct CheckboxDemo{ 30 build(){ 31 Column(){ 32 Flex({}){ 33 CheckboxGroup({}) 34 Text('水果清单') 35 } 36 Flex({}){ 37 Checkbox({}) 38 Text('苹果') 39 } 40 Flex({}){ 41 Checkbox({}) 42 Text('菠萝') 43 } 44 Flex({}){ 45 Checkbox({}) 46 Text('柚子') 47 } 48 Button('删除') 49 } 50 } 51 } 52 ``` 53 框架搭好了,看下效果: 54 55  56 57 可以看到主选框和选项对齐了,接下来我们来调整下样式。 58 先给CheckboxGroup取个名字:fruit_list,然后为各个Checkbox添加相同的group名称,这样就可以将Checkbox挂靠到CheckboxGroup下,剩下的就是给各个组件添加margin、fontSize等通用属性了,不清楚各个组件有哪些属性的请自行查阅组件参考,具体代码如下: 59 ```ts 60 @Component 61 struct CheckboxDemo{ 62 build(){ 63 Column(){ 64 Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 65 // 将CheckboxGroup命名为'fruit_list' 66 CheckboxGroup({group: 'fruit_list'}) 67 .selectedColor('#007DFF') 68 Text('水果清单') 69 .margin({right:20}) 70 .fontSize(14) 71 .lineHeight(20) 72 .fontColor('#182431') 73 .fontWeight(FontWeight.Bold) 74 } 75 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 76 // 通过group参数将Checkbox挂到CheckboxGroup下 77 Checkbox({name:'苹果',group:'fruit_list'}) 78 .selectedColor('#007DFF') 79 Text('苹果') 80 .margin({right:20}) 81 .fontSize(14) 82 .lineHeight(20) 83 .fontColor('#182431') 84 .fontWeight(500) 85 } 86 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 87 Checkbox({name:'菠萝',group:'fruit_list'}) 88 .selectedColor('#007DFF') 89 Text('菠萝') 90 .margin({right:20}) 91 .fontSize(14) 92 .lineHeight(20) 93 .fontColor('#182431') 94 .fontWeight(500) 95 } 96 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 97 Checkbox({name:'柚子',group:'fruit_list'}) 98 .selectedColor('#007DFF') 99 Text('柚子') 100 .margin({right:20}) 101 .fontSize(14) 102 .lineHeight(20) 103 .fontColor('#182431') 104 .fontWeight(500) 105 } 106 Button('删除') 107 .margin({top:20,left:35}) 108 .fontSize(15) 109 .padding({top:5,bottom:5,left:15,right:15}) 110 } 111 } 112 } 113 ``` 114 我们再来看下效果,发现多选框的布局已经正常了: 115 116  1172. 简化代码。 118 当前代码重复性很高,包含Checkbox的三个Flex的结构完全一样,我们可以简化一下。把重复的结构通过@Builder抽取出来作为一个自定义组件,用到的地方进行引用即可;每个Flex呈现的内容不同,那就将不同的内容作为参数传入。具体代码如下: 119 ```ts 120 @Component 121 struct CheckboxDemo{ 122 // flexNameList存储checkbox选项的文本内容;使用@State修饰后,flexNameList发生变化,UI会同步刷新 123 @State flexNameList:string[] = ['苹果','菠萝','柚子'] 124 @Builder 125 // 将重复内容封装成flexItem,通过参数checkboxName为Text组件传入显示文本,通过groupName绑定CheckboxGroup 126 flexItem(checkboxName:string,groupName:string){ 127 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 128 Checkbox({ name:checkboxName, group:groupName}) 129 .selectedColor('#007DFF') 130 Text(checkboxName) 131 .margin({right:20}) 132 .fontSize(14) 133 .lineHeight(20) 134 .fontColor('#182431') 135 .fontWeight(500) 136 }.margin({ left: 36 }) 137 } 138 139 build(){ 140 Column(){ 141 Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 142 CheckboxGroup({group: 'fruit_list'}) 143 .selectedColor('#007DFF') 144 Text('水果清单') 145 .margin({right:20}) 146 .fontSize(14) 147 .lineHeight(20) 148 .fontColor('#182431') 149 .fontWeight(FontWeight.Bold) 150 } 151 // 通过ForEach遍历flexNameList循环渲染生成UI 152 ForEach(this.flexNameList,(item:any)=>{ 153 // 引用封装的flexItem模板 154 this.flexItem(item,'fruit_list') 155 }) 156 157 Button('删除') 158 .margin({top:20,left:35}) 159 .fontSize(15) 160 .padding({top:5,bottom:5,left:15,right:15}) 161 }.alignItems(HorizontalAlign.Center) 162 } 163 } 164 ``` 1653. 添加删除逻辑。 166 本例中是通过以下方式实现删除操作的:将选中的水果项从flexNameList中删除(为方便展示,本文直接将数据存储在数组中,实际开发需要对接数据库),由于flexNameList被@State修饰,所以其发生变化时会重新执行Build(),从而完成UI刷新,展示删除后的选项。 167 要实现上述逻辑,首先需要获取到被选中的水果项。这里可以通过CheckboxGroup的onChange回调获取,当选项的状态发生变化时,会触发回调并返回各选项的选中状态。 168 具体代码如下: 169 ```ts 170 @Component 171 struct CheckboxDemo{ 172 ... 173 // itemStatus用来存储各选项的选中状态 174 private itemStatus: CheckboxGroupResult 175 ... 176 build(){ 177 Column(){ 178 Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 179 CheckboxGroup({group: 'fruit_list'}) 180 .selectedColor('#007DFF') 181 // 选项状态发生变化时触发onChange回调,各选项的选中状态储存在itemName中并返回,通过itemStatus.name可以获取到被选中的选项列表 182 .onChange((itemName: CheckboxGroupResult) => { 183 this.itemStatus = itemName 184 }) 185 ... 186 }.alignItems(HorizontalAlign.Center) 187 } 188 } 189 ``` 190 将各选项的选中状态存储到itemStatus后,我们就可以通过Button触发删除操作了。当点击删除按钮时,触发删除操作,所以给Button添加onClick事件,并添加删除逻辑。代码如下: 191 ```ts 192 @Component 193 struct CheckboxDemo{ 194 ...... 195 // itemStatus用来存储各选项的选中状态 196 private itemStatus: CheckboxGroupResult 197 ...... 198 build(){ 199 Column(){ 200 Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 201 CheckboxGroup({group: 'fruit_list'}) 202 .selectedColor('#007DFF') 203 // 选项状态发生变化时触发onChange回调,各选项的选中状态储存在itemName中并返回,通过itemStatus.name可以获取到被选中的选项列表 204 .onChange((itemName: CheckboxGroupResult) => { 205 this.itemStatus = itemName 206 }) 207 ...... 208 Button('删除') 209 .margin({top:20,left:35}) 210 .fontSize(15) 211 .padding({top:5,bottom:5,left:15,right:15}) 212 // 点击触发删除操作 213 .onClick(()=>{ 214 // 被选中的项存储在this.itemStatus.name列表中 215 for(let i of this.itemStatus.name){ 216 // 从flexNameList中删除被选中的项,刷新UI 217 this.flexNameList.splice(this.flexNameList.indexOf(i),1) 218 } 219 }) 220 }.alignItems(HorizontalAlign.Center) 221 } 222 } 223 ``` 2244. 添加删除确认框。 225 使用promptAction模块调用showDialog方法弹出对话框,然后将删除操作绑定到对话框的确定按钮,具体代码如下: 226 ```ts 227 // 导入promptAction模块 228 import promptAction from '@ohos.promptAction'; 229 @Component 230 struct CheckboxDemo{ 231 ...... 232 // itemStatus用来存储各选项的选中状态 233 private itemStatus: CheckboxGroupResult 234 ...... 235 build(){ 236 Column(){ 237 Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}){ 238 CheckboxGroup({group: 'fruit_list'}) 239 .selectedColor('#007DFF') 240 // 选项状态发生变化时触发onChange回调,各选项的选中状态储存在itemName中并返回,通过itemStatus.name可以获取到被选中的选项列表 241 .onChange((itemName: CheckboxGroupResult) => { 242 this.itemStatus = itemName 243 }) 244 ...... 245 Button('删除') 246 .margin({top:20,left:35}) 247 .fontSize(15) 248 .padding({top:5,bottom:5,left:15,right:15}) 249 // 点击触发删除操作 250 .onClick(()=>{ 251 // 调用对话框 252 promptAction.showDialog({ 253 title:'', 254 message:'确定删除吗?', 255 buttons:[ 256 {text:'取消', color:'#000000'}, 257 {text:'确定', color:'#000000'} 258 ] 259 }) 260 // 用户选择通过data回传,当data.index为1时,用户选择确定,当data.index为0时,用户选择取消 261 .then(data=>{ 262 // 当用户选择确定时,进行删除操作 263 if(data.index===1){ 264 // 被选中的项存储在this.itemStatus.name列表中 265 for(let i of this.itemStatus.name){ 266 // 从flexNameList中删除被选中的项,刷新UI 267 this.flexNameList.splice(this.flexNameList.indexOf(i),1) 268 } 269 } 270 }) 271 }) 272 }.alignItems(HorizontalAlign.Center) 273 } 274 } 275 ``` 276## 完整代码 277本例完整代码如下: 278```ts 279import promptAction from '@ohos.promptAction'; 280 281@Entry 282@Component 283struct CheckboxDemo{ 284 @State flexNameList:string[] = ['苹果','菠萝','柚子'] 285 private itemStatus:CheckboxGroupResult 286 @Builder 287 flexItem(checkboxName:string,groupName:string){ 288 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 289 Checkbox({ name:checkboxName, group:groupName}) 290 .selectedColor('#007DFF') 291 Text(checkboxName) 292 .margin({right:20}) 293 .fontSize(14) 294 .lineHeight(20) 295 .fontColor('#182431') 296 .fontWeight(500) 297 }.margin({ left: 36 }) 298 } 299 300 build() { 301 Column() { 302 if (this.flexNameList.length != 0){ 303 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 304 CheckboxGroup({ group: 'fruit_list' }) 305 .selectedColor('#007DFF') 306 .onChange((itemName: CheckboxGroupResult) => { 307 this.itemStatus = itemName 308 }) 309 Text('水果清单') 310 .margin({right:20}) 311 .fontSize(14) 312 .lineHeight(20) 313 .fontColor('#182431') 314 .fontWeight(FontWeight.Bold) 315 }.margin({top:150}) 316 317 ForEach(this.flexNameList,(item:any)=>{ 318 this.flexItem(item,'fruit_list') 319 }) 320 321 Button("删除") 322 .margin({top:20,left:35}) 323 .fontSize(15) 324 .padding({top:5,bottom:5,left:15,right:15}) 325 .onClick(()=>{ 326 promptAction.showDialog({ 327 title:'', 328 message:'确定删除吗?', 329 buttons:[ 330 {text:'取消', color:'#000000'}, 331 {text:'确定', color:'#000000'} 332 ] 333 }) 334 .then(data=>{ 335 if(data.index===1){ 336 for(let i of this.itemStatus.name){ 337 this.flexNameList.splice(this.flexNameList.indexOf(i),1) 338 } 339 } 340 }) 341 }) 342 }else{ 343 344 } 345 }.alignItems(HorizontalAlign.Center) 346 } 347} 348``` 349## 参考 350 351- [ChecckboxGroup](../application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-checkboxgroup.md) 352- [Checkbox](../application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-checkbox.md) 353- [Flex](../application-dev/reference/apis-arkui/arkui-ts/ts-container-flex.md) 354- [Button](../application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-button.md) 355- [ohos.promptAction (弹窗)](../application-dev/reference/apis-as/js-apis-promptAction.md) 356- [ForEach循环渲染](../application-dev/quick-start/arkts-rendering-control-foreach.md) 357- [@State状态管理](../application-dev/quick-start/arkts-state.md) 358- [@Builder动态构建UI元素](../application-dev/quick-start/arkts-builder.md)