page.mdx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { pageMetadata } from "@/lib/page-metadata"
  2. export const metadata = pageMetadata("docs/computed-values")
  3. # Computed Values
  4. Derive dynamic prop values using registered functions or string templates.
  5. ## `$template` — String Interpolation
  6. Use `{ "$template": "..." }` to embed state values into a string. References use `${/path}` syntax where the path is a JSON Pointer:
  7. ```json
  8. {
  9. "type": "Text",
  10. "props": {
  11. "text": { "$template": "Hello, ${/user/name}! You have ${/inbox/count} messages." }
  12. },
  13. "children": []
  14. }
  15. ```
  16. If state is `{ "user": { "name": "Alice" }, "inbox": { "count": 3 } }`, the text renders as "Hello, Alice! You have 3 messages."
  17. Missing paths resolve to an empty string.
  18. ## `$computed` — Registered Functions
  19. Use `{ "$computed": "<name>", "args": { ... } }` to call a named function registered in your catalog. Each arg can be a literal value or any prop expression (`$state`, `$item`, `$cond`, etc.):
  20. ```json
  21. {
  22. "type": "Text",
  23. "props": {
  24. "text": {
  25. "$computed": "fullName",
  26. "args": {
  27. "first": { "$state": "/form/firstName" },
  28. "last": { "$state": "/form/lastName" }
  29. }
  30. }
  31. },
  32. "children": []
  33. }
  34. ```
  35. ### Registering Functions
  36. Functions are registered in the catalog and provided at runtime.
  37. **Catalog definition (for AI prompt generation):**
  38. ```typescript
  39. import { defineCatalog } from '@json-render/core';
  40. import { schema } from '@json-render/react/schema';
  41. const catalog = defineCatalog(schema, {
  42. components: { /* ... */ },
  43. functions: {
  44. fullName: {
  45. description: 'Combines first and last name into a full name',
  46. },
  47. formatCurrency: {
  48. description: 'Formats a number as currency',
  49. },
  50. },
  51. });
  52. ```
  53. **Runtime implementation:**
  54. ```tsx
  55. import { JSONUIProvider } from '@json-render/react';
  56. const functions = {
  57. fullName: (args) => `${args.first ?? ''} ${args.last ?? ''}`.trim(),
  58. formatCurrency: (args) => {
  59. const value = Number(args.value ?? 0);
  60. return new Intl.NumberFormat('en-US', {
  61. style: 'currency',
  62. currency: (args.currency as string) ?? 'USD',
  63. }).format(value);
  64. },
  65. };
  66. <JSONUIProvider registry={registry} functions={functions}>
  67. <Renderer spec={spec} registry={registry} />
  68. </JSONUIProvider>
  69. ```
  70. ### Using with `createRenderer`
  71. ```tsx
  72. const MyRenderer = createRenderer(catalog, components);
  73. <MyRenderer
  74. spec={spec}
  75. functions={functions}
  76. />
  77. ```
  78. ## Combining Expressions
  79. `$computed` args can use any expression type. This example computes a total from repeat item fields:
  80. ```json
  81. {
  82. "$computed": "lineTotal",
  83. "args": {
  84. "price": { "$item": "price" },
  85. "quantity": { "$item": "quantity" }
  86. }
  87. }
  88. ```
  89. ## Next
  90. - [Watchers](/docs/watchers) — react to state changes with cascading actions
  91. - [Data Binding](/docs/data-binding) — all expression types
  92. - [Validation](/docs/validation) — validate form inputs