1# Loading Web Pages 2 3 4Page loading is a basic capability of the **Web** component. Depending on the data source, page loading falls into three types: loading of network pages, loading of local pages, and loading of HTML rich text data. 5 6 7If you need to obtain online resources when loading a page, declare the network access permission in the **module.json5** file. For details, see [Declaring Permissions](../security/AccessToken/declare-permissions.md). 8 9 ``` 10 "requestPermissions":[ 11 { 12 "name" : "ohos.permission.INTERNET" 13 } 14 ] 15 ``` 16 17## Loading Network Pages 18 19You can specify the default network page to be loaded when creating a **Web** component. After the default network page is loaded, call [loadUrl()](../reference/apis-arkweb/js-apis-webview.md#loadurl) if you want to change the network page displayed by the **Web** component. The value of the first parameter **src** of the **Web** component cannot be dynamically changed through a state variable (for example, @State). To change the value, call [loadUrl()](../reference/apis-arkweb/js-apis-webview.md#loadurl). 20 21 22In the following example, after the **www.\example.com** page is loaded by the **Web** component, **loadUrl** is called to change the displayed page to **www\.example1.com**. 23 24 25 26```ts 27// xxx.ets 28import { webview } from '@kit.ArkWeb'; 29import { BusinessError } from '@kit.BasicServicesKit'; 30 31@Entry 32@Component 33struct WebComponent { 34 controller: webview.WebviewController = new webview.WebviewController(); 35 36 build() { 37 Column() { 38 Button('loadUrl') 39 .onClick(() => { 40 try { 41 // Upon button clicking, call loadUrl to redirect to www.example1.com. 42 this.controller.loadUrl('www.example1.com'); 43 } catch (error) { 44 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 45 } 46 }) 47 // When creating a Web component, set the default network page to be loaded to www.example.com. 48 Web({ src: 'www.example.com', controller: this.controller }) 49 } 50 } 51} 52``` 53 54 55## Loading Local Pages 56 57The following example shows how to load a local page file. 58 59Local page files are stored in the application's **rawfile** directory. You can specify the local page to be loaded by default when creating a **Web** component. After page loading is complete, you can call [loadUrl()](../reference/apis-arkweb/js-apis-webview.md#loadurl) to change the displayed page of the **Web** component. 60 61To reference a local CSS file when loading a local HTML file, perform the following steps: 62 63```html 64<link rel="stylesheet" href="resource://rawfile/xxx.css"> 65<link rel="stylesheet" href="file:// /data/storage/el2/base/haps/entry/cache/xxx.css">// Load the local CSS file in the sandbox path. 66``` 67 68- Local page file in the application's resources/rawfile directory: 69 70 **Figure 1** Path of local page files 71 72  73 74 75- Application code: 76 77 ```ts 78 // xxx.ets 79 import { webview } from '@kit.ArkWeb'; 80 import { BusinessError } from '@kit.BasicServicesKit'; 81 82 @Entry 83 @Component 84 struct WebComponent { 85 controller: webview.WebviewController = new webview.WebviewController(); 86 87 build() { 88 Column() { 89 Button('loadUrl') 90 .onClick(() => { 91 try { 92 // Upon button clicking, call loadUrl to redirect to local1.html. 93 this.controller.loadUrl($rawfile("local1.html")); 94 } catch (error) { 95 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 96 } 97 }) 98 // When creating a Web component, load the local.html file through $rawfile. 99 Web({ src: $rawfile("local.html"), controller: this.controller }) 100 } 101 } 102 } 103 ``` 104 105 106- Code of the **local.html** page: 107 108 ```html 109 <!-- local.html --> 110 <!DOCTYPE html> 111 <html> 112 <body> 113 <p>Hello World</p> 114 </body> 115 </html> 116 ``` 117 118- Code of the **local1.html** page: 119 120 ```html 121 <!-- local1.html --> 122 <!DOCTYPE html> 123 <html> 124 <body> 125 <p>This is local1 page</p> 126 </body> 127 </html> 128 ``` 129 130Example of loading local page files in the sandbox: 131 1321. Obtain the sandbox path through the constructed singleton object **GlobalContext**. 133 134 ```ts 135 // GlobalContext.ets 136 export class GlobalContext { 137 private constructor() {} 138 private static instance: GlobalContext; 139 private _objects = new Map<string, Object>(); 140 141 public static getContext(): GlobalContext { 142 if (!GlobalContext.instance) { 143 GlobalContext.instance = new GlobalContext(); 144 } 145 return GlobalContext.instance; 146 } 147 148 getObject(value: string): Object | undefined { 149 return this._objects.get(value); 150 } 151 152 setObject(key: string, objectClass: Object): void { 153 this._objects.set(key, objectClass); 154 } 155 } 156 ``` 157 158 ```ts 159 // xxx.ets 160 import { webview } from '@kit.ArkWeb'; 161 import { GlobalContext } from '../GlobalContext'; 162 163 let url = 'file://' + GlobalContext.getContext().getObject("filesDir") + '/index.html'; 164 165 @Entry 166 @Component 167 struct WebComponent { 168 controller: webview.WebviewController = new webview.WebviewController(); 169 170 build() { 171 Column() { 172 // Load the files in the sandbox. 173 Web({ src: url, controller: this.controller }) 174 } 175 } 176 } 177 ``` 178 1792. Modify the **EntryAbility.ets** file. 180 181 The following uses **filesDir** as an example to describe how to obtain the path of the sandbox. For details about how to obtain other paths, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths). 182 183 ```ts 184 // xxx.ets 185 import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; 186 import { webview } from '@kit.ArkWeb'; 187 import { GlobalContext } from '../GlobalContext'; 188 189 export default class EntryAbility extends UIAbility { 190 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 191 // Data synchronization between the UIAbility component and UI can be implemented by binding filesDir to the GlobalContext object. 192 GlobalContext.getContext().setObject("filesDir", this.context.filesDir); 193 console.log("Sandbox path is " + GlobalContext.getContext().getObject("filesDir")); 194 } 195 } 196 ``` 197 198 HTML file to be loaded: 199 200 ```html 201 <!-- index.html --> 202 <!DOCTYPE html> 203 <html> 204 <body> 205 <p>Hello World</p> 206 </body> 207 </html> 208 ``` 209 210 211## Loading HTML Rich Text Data 212 213The **Web** component provides the [loadData()](../reference/apis-arkweb/js-apis-webview.md#loaddata) API for you to load HTML rich text data. This API is applicable if you want to display some page sections instead of the entire page. To load a large number of HTML files, set **baseUrl** to data. 214 215```ts 216// xxx.ets 217import { webview } from '@kit.ArkWeb'; 218import { BusinessError } from '@kit.BasicServicesKit'; 219 220@Entry 221@Component 222struct WebComponent { 223 controller: webview.WebviewController = new webview.WebviewController(); 224 225 build() { 226 Column() { 227 Button('loadData') 228 .onClick(() => { 229 try { 230 // Upon button clicking, call loadData to load HTML rich text data. 231 this.controller.loadData( 232 "<html><body bgcolor=\"white\">Source:<pre>source</pre></body></html>", 233 "text/html", 234 "UTF-8" 235 ); 236 } catch (error) { 237 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 238 } 239 }) 240 // When creating a Web component, set the default network page to be loaded to www.example.com. 241 Web({ src: 'www.example.com', controller: this.controller }) 242 } 243 } 244} 245``` 246 247The **Web** component can load HTML strings using data urls. 248 249```ts 250// xxx.ets 251import { webview } from '@kit.ArkWeb'; 252import { BusinessError } from '@kit.BasicServicesKit'; 253 254@Entry 255@Component 256struct WebComponent { 257 controller: webview.WebviewController = new webview.WebviewController(); 258 htmlStr: string = "data:text/html, <html><body bgcolor=\"white\">Source:<pre>source</pre></body></html>"; 259 260 build() { 261 Column() { 262 // When creating a Web component, set the default network page to be loaded to htmlStr. 263 Web({ src: this.htmlStr, controller: this.controller }) 264 } 265 } 266} 267``` 268 269## Dynamically Creating a Web Component 270**Web** components can be created with commands. Components created in this mode are not immediately mounted to the component tree, that is, they are not presented to users (their state is **Hidden** or **InActive**). You can dynamically mount the components as required in subsequent use. It is recommended that the number of **Web** instances started in the background be less than or equal to 200. 271 272```ts 273// Carrier ability 274// EntryAbility.ets 275import { createNWeb } from "../pages/common" 276onWindowStageCreate(windowStage: window.WindowStage): void { 277 windowStage.loadContent('pages/Index', (err, data) => { 278 // Dynamically create a Web component (UIContext needs to be passed in). The component can be created at any time after loadContent() is called. 279 createNWeb("https://www.example.com", windowStage.getMainWindowSync().getUIContext()); 280 if (err.code) { 281 return; 282 } 283 }); 284} 285``` 286```ts 287// Create a NodeController instance. 288// common.ets 289import { UIContext, NodeController, BuilderNode, Size, FrameNode } from '@kit.ArkUI'; 290import { webview } from '@kit.ArkWeb'; 291 292// @Builder contains the specific content of the dynamically created component. 293// Data is an input parameter of encapsulation class. 294class Data{ 295 url: string = "https://www.example.com"; 296 controller: WebviewController = new webview.WebviewController(); 297} 298 299@Builder 300function WebBuilder(data:Data) { 301 Column() { 302 Web({ src: data.url, controller: data.controller }) 303 .width("100%") 304 .height("100%") 305 } 306} 307 308let wrap = wrapBuilder<Data[]>(WebBuilder); 309 310// NodeController is used to control and report the behavior of the node on the NodeContainer. This function must be used together with NodeContainer. 311export class myNodeController extends NodeController { 312 private rootnode: BuilderNode<Data[]> | null = null; 313 // This function must be overridden. It is used to build the number of nodes and return the number of nodes mounted to the corresponding NodeContainer. 314 // Call it when the NodeContainer is created or call rebuild() to refresh. 315 makeNode(uiContext: UIContext): FrameNode | null { 316 console.log(" uicontext is undefined : "+ (uiContext === undefined)); 317 if (this.rootnode != null) { 318 // Return the FrameNode. 319 return this.rootnode.getFrameNode(); 320 } 321 // Return null to detach the dynamic component from the bound node. 322 return null; 323 } 324 // Called when the layout size changes. 325 aboutToResize(size: Size) { 326 console.log("aboutToResize width : " + size.width + " height : " + size.height ); 327 } 328 329 // Called when the NodeContainer bound to the controller is about to appear. 330 aboutToAppear() { 331 console.log("aboutToAppear"); 332 } 333 334 // Called when the NodeContainer bound to the controller is about to disappear. 335 aboutToDisappear() { 336 console.log("aboutToDisappear"); 337 } 338 339 // This function is a custom function and can be used as an initialization function. 340 // Initialize BuilderNode through UIContext, and then initialize the content in @Builder through the build API in BuilderNode. 341 initWeb(url:string, uiContext:UIContext, control:WebviewController) { 342 if(this.rootnode != null) 343 { 344 return; 345 } 346 // Create a node. UIContext is required. 347 this.rootnode = new BuilderNode(uiContext); 348 // Create a dynamic Web component. 349 this.rootnode.build(wrap, { url:url, controller:control }); 350 } 351} 352// Create a map to save the required NodeController. 353let NodeMap:Map<string, myNodeController | undefined> = new Map(); 354// Create a map to save the required WebViewController. 355let controllerMap:Map<string, WebviewController | undefined> = new Map(); 356 357// UIContext is required for initialization and needs to be obtained from the ability. 358export const createNWeb = (url: string, uiContext: UIContext) => { 359 // Create a NodeController instance. 360 let baseNode = new myNodeController(); 361 let controller = new webview.WebviewController() ; 362 // Initialize the custom Web component. 363 baseNode.initWeb(url, uiContext, controller); 364 controllerMap.set(url, controller) 365 NodeMap.set(url, baseNode); 366} 367// Customize the API for obtaining the NodeController. 368export const getNWeb = (url : string) : myNodeController | undefined => { 369 return NodeMap.get(url); 370} 371``` 372```ts 373// Use the Page page of the NodeController. 374// Index.ets 375import { getNWeb } from "./common" 376@Entry 377@Component 378struct Index { 379 build() { 380 Row() { 381 Column() { 382 // NodeContainer is used to bind to the NodeController. A rebuild call triggers makeNode. 383 // The Page page is bound to the NodeController through the NodeContainer API to display the dynamic component. 384 NodeContainer(getNWeb("https://www.example.com")) 385 .height("90%") 386 .width("100%") 387 } 388 .width('100%') 389 } 390 .height('100%') 391 } 392} 393 394``` 395**Common troubleshooting procedure** 3961. Check the network permission configuration of the application. 397 398 Check whether the network permission has been added to the **module.json5** file. For details, see [Declaring Permissions in the Configuration File](../security/AccessToken/declare-permissions.md). 399 ```ts 400 "requestPermissions":[ 401 { 402 "name" : "ohos.permission.INTERNET" 403 } 404 ] 405 ``` 4062. Check the logic for binding **NodeContainer** to nodes. 407 408 Check whether the node is added to the component tree. You are advised to add **Text** above the existing **Web** component (see the following example). If **Text** is not displayed when a white screen is displayed, check the binding between **NodeContainer** and the node. 409 ```ts 410 @Builder 411 function WebBuilder(data:Data) { 412 Column() { 413 Text('test') 414 Web({ src: data.url, controller: data.controller }) 415 .width("100%") 416 .height("100%") 417 } 418 } 419 ``` 4203. Check the visibility of the **Web** component. 421 422 If the entire node has been added to the tree, you can view the [WebPattern::OnVisibleAreaChange](../reference/apis-arkui/arkui-ts/ts-universal-component-visible-area-change-event.md#onvisibleareachange) log to check whether the **Web** component is visible. Invisible **Web** components may cause a white screen. 423## Samples 424 425The following samples are provided to help you better understand how to develop the **Web** component: 426 427- [Browser (ArkTS) (Full SDK) (API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-5.0.1-Release/code/BasicFeature/Web/Browser) 428