ContentInjectionExample.vala 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using Astralis;
  2. using Invercargill;
  3. using Invercargill.DataStructures;
  4. using Inversion;
  5. using Spry;
  6. /**
  7. * CardComponent: A wrapper component that accepts content via spry-content.
  8. *
  9. * The <spry-content/> tag acts as a placeholder where parent components
  10. * can inject their own content. When a parent uses:
  11. *
  12. * <spry-component name="CardComponent" sid="my-card">
  13. * ...content here...
  14. * </spry-component>
  15. *
  16. * The nested content replaces the <spry-content/> tag in the rendered output.
  17. */
  18. class CardComponent : Component {
  19. public override string markup { get {
  20. return """
  21. <div class="card" style="border: 2px solid #3b82f6; border-radius: 8px; padding: 20px; margin: 16px 0; background-color: #f8fafc;">
  22. <spry-content/>
  23. </div>
  24. """;
  25. }}
  26. }
  27. /**
  28. * AlertComponent: Another wrapper component styled for warnings/info.
  29. *
  30. * This demonstrates that spry-content can be used in multiple components
  31. * with different styling. The content injection works the same way -
  32. * whatever is nested inside the spry-component tag gets placed where
  33. * <spry-content/> appears.
  34. */
  35. class AlertComponent : Component {
  36. public override string markup { get {
  37. return """
  38. <div class="alert" style="border-left: 4px solid #f59e0b; background-color: #fffbeb; padding: 16px; margin: 16px 0; border-radius: 4px;">
  39. <spry-content/>
  40. </div>
  41. """;
  42. }}
  43. }
  44. /**
  45. * PageComponent: The main page layout that uses CardComponent and AlertComponent.
  46. *
  47. * This component demonstrates content injection by nesting different content
  48. * inside each wrapper component. The nested HTML (headings, paragraphs, etc.)
  49. * will be injected where <spry-content/> appears in each child component.
  50. */
  51. class PageComponent : Component {
  52. public override string markup { get {
  53. return """
  54. <!DOCTYPE html>
  55. <html>
  56. <head>
  57. <title>Content Injection Example</title>
  58. <script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"></script>
  59. <style>
  60. body { font-family: system-ui, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
  61. h1 { color: #1e293b; }
  62. </style>
  63. </head>
  64. <body>
  65. <h1>Spry Content Injection Example</h1>
  66. <p>This page demonstrates the <code>spry-content</code> tag for injecting content into child components.</p>
  67. <!-- Card with welcome content -->
  68. <spry-component name="CardComponent" sid="welcome-card">
  69. <h2 style="margin-top: 0; color: #1e40af;">Welcome!</h2>
  70. <p>This content is injected into the CardComponent. The blue border and padding come from the component's styling.</p>
  71. <p>Any HTML can be placed here - forms, images, other components, etc.</p>
  72. </spry-component>
  73. <!-- Alert with info message -->
  74. <spry-component name="AlertComponent" sid="info-alert">
  75. <span><strong>Notice:</strong> This is an informational alert. The yellow styling and left border come from AlertComponent.</span>
  76. </spry-component>
  77. <!-- Another card with different content -->
  78. <spry-component name="CardComponent" sid="features-card">
  79. <h2 style="margin-top: 0; color: #1e40af;">Features</h2>
  80. <ul>
  81. <li>Components can be reused with different content</li>
  82. <li>Styling is encapsulated in the wrapper component</li>
  83. <li>Content is flexible and parent-controlled</li>
  84. </ul>
  85. </spry-component>
  86. <!-- Alert with warning -->
  87. <spry-component name="AlertComponent" sid="warning-alert">
  88. <span><strong>Warning:</strong> This demonstrates another use of AlertComponent with completely different content.</span>
  89. </spry-component>
  90. </body>
  91. </html>
  92. """;
  93. }}
  94. }
  95. /**
  96. * HomePageEndpoint: Serves the PageComponent.
  97. */
  98. class HomePageEndpoint : Object, Endpoint {
  99. private PageComponent page_component = inject<PageComponent>();
  100. public async Astralis.HttpResult handle_request(Astralis.HttpContext http_context, Astralis.RouteContext route_context) throws Error {
  101. return yield page_component.to_result();
  102. }
  103. }
  104. void main(string[] args) {
  105. int port = args.length > 1 ? int.parse(args[1]) : 8080;
  106. try {
  107. var application = new WebApplication(port);
  108. application.use_compression();
  109. application.add_module<SpryModule>();
  110. application.add_transient<CardComponent>();
  111. application.add_transient<AlertComponent>();
  112. application.add_transient<PageComponent>();
  113. application.add_endpoint<HomePageEndpoint>(new EndpointRoute("/"));
  114. application.run();
  115. } catch (Error e) {
  116. printerr("Error: %s\n", e.message);
  117. Process.exit(1);
  118. }
  119. }