1# ContentSlot: Enabling Hybrid Development 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @sd-wu--> 5<!--Designer: @sunbees--> 6<!--Tester: @liuli0427--> 7<!--Adviser: @zhang_yixin13--> 8 9The **ContentSlot** component enables rendering and management of components created using C APIs on the native layer. 10 11With support for hybrid development, **ContentSlot** serves the recommended placeholder component when the container is an ArkTS component with child components created on the native side. 12 13## APIs 14 15### ArkTS-side APIs 16 17| Name | Description| 18| ------- | -------- | 19| ContentSlot(content: Content) | Container component for hybrid development. The **Content** object acts as the manager for **ContentSlot**, providing native-side APIs to register tree attachment and detachment callbacks and manage child components.| 20 21```ts 22abstract class Content { 23} 24``` 25 26### Native-side APIs 27 28| Name| Description| 29| -------- | -------- | 30|OH_ArkUI_NodeContent_RegisterCallback(ArkUI_NodeContentHandle content, ArkUI_NodeContentCallback callback)|Registers an event with the **Content** manager.| 31|OH_ArkUI_NodeContentEvent_GetEventType(ArkUI_NodeContentEvent* event)|Obtains the type of the event triggered on the **Content**.| 32|OH_ArkUI_NodeContent_AddNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)|Adds a child component to **Content**.| 33|OH_ArkUI_NodeContent_InsertNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node, int32_t position)|Inserts a child component into **Content**.| 34|OH_ArkUI_NodeContent_RemoveNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)|Removes a child component from **Content**.| 35|OH_ArkUI_GetNodeContentFromNapiValue(napi_env env, napi_value value, ArkUI_NodeContentHandle* content)|Obtains the pointer to **Content** in ArkTS from the native side.| 36|OH_ArkUI_NodeContentEvent_GetNodeContentHandle(ArkUI_NodeContentEvent* event)|Obtains the **Content** object that triggers the attach and detach events.| 37|OH_ArkUI_NodeContent_SetUserData(ArkUI_NodeContentHandle content, void* userData)|Sets the custom attributes on **Content**.| 38|OH_ArkUI_NodeContent_GetUserData(ArkUI_NodeContentHandle content)|Obtains the custom attributes from **Content**.| 39|typedef enum {<br> NOTE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW = 0,<br> NOTE_CONTENT_EVENT_ON_DETACH_FROM_WINDOW = 1,<br>} ArkUI_NodeContentEventType|Enumerates the event types on **Content**.| 40 41## Development and Implementation 42 43### ArkTS-side Implementation 44 45```ts 46import { nativeNode } from 'libNativeNode.so'; // Developer-implemented .so file. 47import { NodeContent } from '@kit.ArkUI'; 48 49@Entry 50@Component 51struct Parent { 52 private nodeContent: Content = new NodeContent(); 53 54 aboutToAppear() { 55 // Create a node through the C API and add it to the nodeContent manager. 56 nativeNode.createNativeNode(this.nodeContent); 57 } 58 59 build() { 60 Column() { 61 // Display the native components stored in the nodeContent manager. 62 ContentSlot(this.nodeContent) 63 } 64 } 65} 66``` 67 68### Native-side Implementation 69For details about the basic development knowledge of Node-API, see [Getting Started with the NDK](../../napi/ndk-development-overview.md). 70 71This topic only describes how to implement the logic code related to **ContentSlot**. For details about how to create a component on the native side, see [NDK API Overview](../ndk-build-ui-overview.md). 72 73```c++ 74#include "napi/native_api.h" 75#include "arkui/native_type.h" 76#include "arkui/native_node.h" 77#include "arkui/native_node_napi.h" 78#include "arkui/native_interface.h" 79#include "hilog/log.h" 80 81ArkUI_NodeContentHandle nodeContentHandle_ = nullptr; 82ArkUI_NativeNodeAPI_1 *nodeAPI; 83const unsigned int LOG_PRINT_DOMAIN = 0xFF00; 84 85// Create a 480 vp x 480 vp Column component with a red (0xFFFF0000) background on the native side. For details about how to create a node tree, see ArkUI C API documentation. 86ArkUI_NodeHandle CreateNodeHandle() { 87 ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN); 88 ArkUI_NumberValue value[] = {480}; 89 ArkUI_AttributeItem item{value, 1}; 90 nodeAPI->setAttribute(column, NODE_WIDTH, &item); 91 nodeAPI->setAttribute(column, NODE_HEIGHT, &item); 92 value[0].u32 = 0xFFFF0000; 93 nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &item); 94 return column; 95} 96 97// Native-side implementation of the ArkTS createNativeNode API. 98napi_value CreateNativeNode(napi_env env, napi_callback_info info) { 99 // Solve null pointer and out-of-bounds issues related to Node-API. 100 if ((env == nullptr) || (info == nullptr)) { 101 return nullptr; 102 } 103 104 size_t argc = 1; 105 napi_value args[1] = { nullptr }; 106 if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { 107 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed"); 108 } 109 110 if (argc != 1) { 111 return nullptr; 112 } 113 114 nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>( 115 OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")); 116 117 // Point nodeContentHandle_ to a nodeContent object passed in from ArkTS. 118 OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_); 119 120 if (nodeAPI != nullptr) { 121 if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) { 122 ArkUI_NodeHandle component; 123 // Create a native-side component. 124 component = CreateNodeHandle(); 125 // Add the component to the nodeContent manager. 126 OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component); 127 } 128 } 129 return nullptr; 130} 131``` 132 133### Native-side API Usage 134 135- **Registering Tree Events and Obtaining the Corresponding Content Object** 136 137 ```c++ 138 auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) { 139 ArkUI_NodeContentHandle content = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event); 140 // Additional logic required for different contents. 141 if (OH_ArkUINodeContentEvent_GetEventType(event) = NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) { 142 // Logic to be triggered when an attach event occurs on ContentSlot. 143 } else if (OH_ArkUINodeContentEvent_GetEventType(event) = NODE_CONTENT_EVENT_ON_DETACH_FROM_WINDOW) { 144 // Logic to be triggered when a detach event occurs on ContentSlot. 145 }; 146 }; 147 // Register an event with nodeContent. 148 OH_ArkUI_NodeContent_RegisterCallback(nodeContentHandle_, nodeContentEvent); 149 ``` 150 151- **Adding Child Components** 152 153 ```c++ 154 ArkUINodeHandle component; 155 component = CreateNodeHandle(); 156 // Add the component to the nodeContent manager. 157 OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component); 158 ``` 159 160- **Inserting Child Components** 161 162 ```c++ 163 ArkUINodeHandle component; 164 component = CreateNodeHandle(); 165 // Insert a component into the specified position of the nodeContent manager. 166 OH_ArkUI_NodeContent_InsertNode(nodeContentHandle_, component, position); 167 ``` 168 169- **Removing Child Components** 170 171 ```c++ 172 // Remove a component from the nodeContent manager. 173 OH_ArkUI_NodeContent_RemoveNode(nodeContentHandle_, component); 174 ``` 175 176- **Setting Custom Attributes** 177 178 ```c++ 179 // Create the custom data to be defined. 180 void *userData = CreateUserData(); 181 OH_ArkUI_NodeContent_SetUserData(nodeContentHandle_, userData); 182 ``` 183 184- **Obtaining Custom Attributes** 185 186 ``` 187 void *userData = OH_ArkUI_NodeContent_GetUserData(nodeContentHandle_); 188 ``` 189