You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
BREAKING CHANGE: The `content` property is no longer supported. The `render` property must be used. In some cases, usage of the `shadow` option might be required.
Copy file name to clipboardExpand all lines: docs/component-model/structure.md
+92-67
Original file line number
Diff line number
Diff line change
@@ -12,10 +12,10 @@ The cache mechanism uses equality check to compare values (`nextValue` !== `last
12
12
13
13
## Reserved Keys
14
14
15
-
There are three reserved property names in the definition:
15
+
There are two reserved property names in the definition:
16
16
17
17
*`tag` - a string which sets the custom element tag name
18
-
*`render`and `content`, which expect the value as a function, and have additional options available
18
+
*`render`- expects its value as a function for rendering the internal structure of the custom element
19
19
20
20
## Translation
21
21
@@ -53,7 +53,7 @@ define({
53
53
});
54
54
```
55
55
56
-
Usually, the shorthand definition is more readable and less verbose, but the second one gives more control over the property behavior, as it provides additional options.
56
+
Usually, the shorthand syntax is more readable and less verbose, but the second one gives more control over the property behavior, as it provides additional options.
57
57
58
58
## Attributes
59
59
@@ -286,21 +286,39 @@ define({
286
286
});
287
287
```
288
288
289
-
## `render` & `content`
289
+
## Render
290
290
291
-
The `render`and `content` properties are reserved for the rendering structure of the custom element. The `value` option must be a function, which returns a result of the call to the built-in template engine or a custom update function.
291
+
The `render`property is reserved for the creating structure of the custom element.
292
292
293
-
The library uses internally the `observe` pattern to called function automatically when dependencies change. As the property returns an update function, it can also be called manually, by `el.render()` or `el.content()`.
293
+
The `value` option must be a function, which returns a result of the call to the built-in template engine.
294
294
295
-
> You can use built-in [template engine](/component/templates.md) with those properties without additional code
295
+
The library uses the `observe` pattern to call the function automatically when dependencies change. As the property resolves to the update function, it can also be called manually, by `el.render()`.
296
296
297
-
### Shadow DOM
297
+
### Element's Content
298
298
299
-
Use the`render`key for the internal structure of the custom element, where you can add isolated styles, slot elements, etc.
299
+
By default`render`property creates and updates the contents of the custom element:
300
300
301
301
```javascript
302
-
import { define, html } from"hybrids";
302
+
define({
303
+
tag:"my-element",
304
+
name:"",
305
+
render: ({ name }) =>html`<h1>Hello ${name}!</h1>`,
306
+
});
307
+
```
303
308
309
+
```html
310
+
<my-element>
311
+
<h1>Hello John!</h1>
312
+
</my-element>
313
+
```
314
+
315
+
### Shadow DOM
316
+
317
+
If the root template of the element includes styles or `<slot>` elements, the library renders the content to the shadow DOM:
318
+
319
+
The template with inline styles:
320
+
321
+
```javascript
304
322
define({
305
323
tag:"my-element",
306
324
name:"",
@@ -313,88 +331,95 @@ define({
313
331
});
314
332
```
315
333
316
-
The `render` property provides unique `options` key for passing additional arguments to `host.attachShadow()` method:
317
-
318
-
```ts
319
-
render: {
320
-
value: (host) => { ... },
321
-
options: {
322
-
mode:"open"|"closed",
323
-
delegatesFocus: boolean,
324
-
},
325
-
...
326
-
}
334
+
```html
335
+
<my-element>
336
+
#adopted-stylesheets
337
+
#shadow-root
338
+
<h1>Hello John!</h1>
339
+
</my-element>
327
340
```
328
341
329
-
```javascript
330
-
import { define, html } from"hybrids";
342
+
The template with `<slot>` element:
331
343
344
+
```javascript
332
345
define({
333
346
tag:"my-element",
334
-
render: {
335
-
value:html`<div>...</div>`,
336
-
options: { delegatesFocus:true },
337
-
},
347
+
render: () =>html`
348
+
<divid="container">
349
+
<slot></slot>
350
+
</div>
351
+
`,
338
352
});
339
353
```
340
354
341
-
### Element's Content
355
+
```html
356
+
<my-element>
357
+
#shadow-root
358
+
<div id="container">
359
+
<slot></slot>
360
+
</div>
361
+
</my-element>
362
+
```
342
363
343
-
Use the `content` property for rendering templates in the content of the custom element. By the design, it does not support isolated styles, slot elements, etc.
364
+
!> Only the root template can be used to determine the rendering mode implicitly. The nested template with styles does not force rendering in the Shadow DOM.
344
365
345
-
However, it is the way to build an app-like views structure, which can be rendered as a document content in light DOM. It is easily accessible in developer tools and search engines. For example, form elements (like `<input>`) have to be in the same subtree with the `<form>` element.
366
+
### Explicit Mode
346
367
347
-
```javascript
348
-
import { define, html } from"hybrids";
368
+
Use the `shadow` option to force one of the rendering modes:
349
369
350
-
define({
351
-
tag:"my-element",
352
-
name:"",
353
-
content: ({ name }) =>html`<h1>Hello ${name}!</h1>`
354
-
});
370
+
```ts
371
+
// Disable Shadow DOM (even if the template includes styles or slot elements)
372
+
render: {
373
+
value: (host) =>html`...`.css`...`,
374
+
shadow:false,
375
+
...
376
+
}
377
+
378
+
// Force Shadow DOM
379
+
render: {
380
+
value: (host) =>html`...`,
381
+
shadow:true,
382
+
}
355
383
```
356
384
357
-
### Custom Function
385
+
#### Nested Templates
358
386
359
-
The preferred way is to use a built-in [template engine](/component/templates.md), but you can use any function to update the DOM of the custom element, which accepts the following structure:
387
+
If only your nested template includes styles, you must use the `shadow` option to force rendering in the Shadow DOM explicitly:
360
388
361
389
```javascript
362
-
importReactfrom"react";
363
-
importReactDOMfrom"react-dom";
364
-
365
-
exportdefaultfunctionreactify(fn) {
366
-
return (host) => {
367
-
// get the component using the fn and host element
368
-
constComponent=fn(host);
369
-
370
-
// return the update function
371
-
return (host, target) => {
372
-
ReactDOM.render(Component, target);
373
-
}
374
-
}
375
-
}
390
+
define({
391
+
tag:"my-element",
392
+
show:false,
393
+
render: {
394
+
value: ({ show }) =>html`
395
+
<divid="container">
396
+
${show &&html`<slot></slot>`}
397
+
</div>
398
+
`,
399
+
shadow:true,
400
+
},
401
+
});
376
402
```
377
403
378
-
```javascript
379
-
importreactifyfrom"./reactify.js";
404
+
#### Shadow DOM Options
380
405
381
-
functionMyComponent({ name }) {
382
-
return<div>{name}</div>;
383
-
}
406
+
You can use `shadow` option for passing custom arguments to the `host.attachShadow()` method:
407
+
408
+
```javascript
409
+
import { define, html } from"hybrids";
384
410
385
411
define({
386
412
tag:"my-element",
387
-
render:reactify(({ name }) =><MyComponent name={name} />),
388
-
})
413
+
render: {
414
+
value:html`<div>...</div>`,
415
+
shadow: { mode:"close", delegatesFocus:true },
416
+
},
417
+
});
389
418
```
390
419
391
-
The above example uses the [`factory` pattern](#factories), to produce a function, which accepts the host element and returns the update function, which has `host` and `target` arguments. The `target` argument in the update function can be a `host` or `host.shadowRoot` depending on the property name.
392
-
393
-
!> The other properties from the `host` must be called in the main function body (not in the update function), as only then they will be correctly observed
394
-
395
420
### Reference Internals
396
421
397
-
Both`render`and `content` properties can be used to reference internals of the custom element. The DOM update process is asynchronous, so to avoid rendering timing issues, always use a property as a reference to the target element. If the property depending on `render` or `content` is called before the first update, the update will be triggered manually by calling the function.
422
+
The`render`property can be used to reference internals of the custom element. The DOM update process is asynchronous, so to avoid rendering timing issues, always use the property as a reference to the target element. If the property depending on `render` is called before the first update, the update will be triggered manually by calling the function.
0 commit comments