glimmer-dsl-web 0.2.4 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +271 -50
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +25 -19
- data/lib/glimmer/web/component.rb +2 -0
- data/lib/glimmer-dsl-web/ext/kernel.rb +2 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_form.rb +2 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_form_mvp/models/contact.rb +1 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_form_mvp/presenters/hello_form_mvp_presenter.rb +25 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_form_mvp/views/contact_form.rb +46 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_form_mvp/views/contact_table.rb +42 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_form_mvp.rb +51 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_observer.rb +7 -21
- data/lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb +57 -0
- metadata +18 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45ca1b698d2d53da63a133041ac83c77888d42b1e504bc2fa3b81b54c610ff32
|
4
|
+
data.tar.gz: 91268134dcba4d5d04435d8ee517f7a1e39e277ff0be9487aa7dd99eb1899ee2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68b47d95332b4156d5c04643078cf95bf9d51098b5219836bb1a25eb440d2db25fca55ade3179c64b6587b887b890d4188eb8a91b2f9a32c78ba88027c114774
|
7
|
+
data.tar.gz: efdb2f8bfb640b0fe1ce052cf867c2d0b58f4ceae6284e23178f51d42b296e53dda009794cd08cb7a46ec2cc0894f0a9054c1a903d40bc7c62dae0570eec16e9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.2.6
|
4
|
+
|
5
|
+
- Upgrade to `glimmer-dsl-xml` 1.4.0 to provide access to `html_to_glimmer` converter command (converts legacy HTML to Glimmer DSL syntax)
|
6
|
+
- Upgrade to `glimmer-dsl-css` 1.4.0 to provide access to `css_to_glimmer` converter command (converts legacy CSS to Glimmer DSL syntax)
|
7
|
+
|
8
|
+
## 0.2.5
|
9
|
+
|
10
|
+
- Support `Element#class_name` as an alternative to `Element#class` because `class` is a reserved method in Ruby
|
11
|
+
- Handle case of data-binding an element that has no `type` attribute
|
12
|
+
- Provide `attribute`/`attributes` as aliases for `option`/`options` inside classes mixing `Glimmer::Web::Component` given that the options behave like HTML attributes
|
13
|
+
- Hello, Form MVP! Sample: `require 'glimmer-dsl-web/samples/hello/hello_form_mvp'`
|
14
|
+
- Hello, Observer (Data-Binding)! Sample: `require 'glimmer-dsl-web/samples/hello/hello_observer_data_binding'`
|
15
|
+
|
3
16
|
## 0.2.4
|
4
17
|
|
5
18
|
- Enhance `Kernel#puts` & `Kernel#p` to enable printing any native JS object with `console.log` (without having to manually wrap with `Native`)
|
data/README.md
CHANGED
@@ -1,14 +1,31 @@
|
|
1
|
-
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.2.
|
1
|
+
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.2.6 (Beta)
|
2
2
|
## Ruby in the Browser Web Frontend Framework
|
3
|
+
### Finally, Ruby Developer Productivity, Happiness, and Fun in the Frontend!!!
|
3
4
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-web.svg)](http://badge.fury.io/rb/glimmer-dsl-web)
|
4
5
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
6
|
|
6
7
|
**(Based on Original [Glimmer](https://github.com/AndyObtiva/glimmer) Library Handling World’s Ruby GUI Needs Since 2007. Beware of Imitators!)**
|
7
8
|
|
8
|
-
|
9
|
+
**(Talk Videos: [Intro to Ruby in the Browser](https://youtu.be/4AdcfbI6A4c?si=MmxOrkhIXTDHQoYi) & [Frontend Ruby with Glimmer DSL for Web](https://youtu.be/rIZ-ILUv9ME?si=raygUXVPd_7ypWuE))**
|
10
|
+
|
11
|
+
You can finally have Ruby developer happiness and productivity in the Frontend! No more wasting time splitting your resources across multiple languages, using badly engineered, over-engineered, or premature-optimization-obsessed JavaScript libraries, fighting JavaScript build issues (e.g. webpack), or rewriting Ruby Backend code in Frontend JavaScript. With [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), you can have an exponential jump in development productivity (2x or higher), time-to-release (1/2 or less time), cost (1/2 or cheaper), and maintainability (~50% the code that is simpler and more readable) over JavaScript libraries like React, Angular, Ember, Vue, and Svelte, while being able to reuse Backend Ruby code as is in the Frontend for faster interactions when needed. [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c) finally fulfills every highly-productive Rubyist's dream by bringing Ruby productivity fun to Frontend Development, the same productivity fun you had for years and decades in Backend Development.
|
12
|
+
|
13
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web Frontends using [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), as per [Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby](https://youtu.be/knutsgHTrfQ?t=789). It supports Rails' principle of the One Person Framework by not requiring any extra developers with JavaScript expertise, yet enabling Ruby (Backend) Software Engineers to develop the Frontend with Ruby code that is better than any JavaScript code produced by JS developers. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with [DSLs](https://martinfowler.com/books/dsl.html) and [TIMTOWTDI](https://en.wiktionary.org/wiki/TMTOWTDI#English)) and the Rails way ([Convention over Configuration](https://rubyonrails.org/doctrine)) in building Isomorphic Ruby on Rails Applications. It provides a Ruby [HTML DSL](#usage), which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) [Data-Binding](#hello-data-binding) (using `<=`) and Bidirectional (Two-Way) [Data-Binding](#hello-data-binding) (using `<=>`). Dynamic rendering (and re-rendering) of HTML content is also supported via [Content Data-Binding](#hello-content-data-binding). Modular design is supported with [Glimmer Web Components](#hello-component). And, a Ruby CSS DSL is supported with the included [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css). Many [samples](#samples) are demonstrated in the [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) (there is a very minimal [Standalone [No Rails] static site sample app](https://github.com/Largo/glimmer-dsl-web-standalone-demo) too). You can finally live in pure Rubyland on the Web in both the frontend and backend with [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web)!
|
14
|
+
|
15
|
+
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) aims to be a very simple Ruby-based drop-in replacement for your existing JavaScript Frontend library (e.g. React, Angular, Vue, Ember, Svelte) or your JavaScript Frontend layer in general. It does not change how your Frontend interacts with the Backend, meaning you can continue to write Rails Backend API endpoints as needed and make Ajax HTTP requests or read data embedded in elements, but from [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c). Whatever is possible in JavaScript is possible when using Glimmer DSL for Web as it integrates with any existing JavaScript library. The [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) demonstrates how to [make Ajax HTTP calls](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector/models/sample_selector_presenter.rb) and how to [integrate with a JavaScript library](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/layouts/application.html.erb) (highlightjs) that performs [code syntax highlighting](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector.rb).
|
16
|
+
|
17
|
+
After looking through the [samples](#samples) below, read the [FAQ (Frequently Asked Questions)](#faq) to learn more about how Glimmer DSL for Web compares to other approaches/libraries like Hotwire (Turbo), Phlex, ViewComponent, Angular, Vue, React, Svelte, and other JS frameworks.
|
18
|
+
|
19
|
+
Anyone not considering this kind of technology in 2024 is like someone stuck in the dark ages riding horse carriage (e.g. JavaScript developers using frameworks like React) despite flying cars having been invented already and providing exponential jumps in productivity (way more than small linear jumps provided by some JavaScript libraries). Obviously, those who do make this jump will end up winning their work over from customers and beating the competition while delivering the best Frontend value possible to customers.
|
20
|
+
|
21
|
+
(Attention Software Engineers, Bloggers, and Contributors: Please use Glimmer DSL for Web in web projects, blog about it, and submit a PR with your article, project, and/or open-source-repo added to the README. Also, I give everyone permission to present this project at their local Ruby user group, local Software Engineering meetup, or Software Conferences outside of North America (e.g. Europe). I am willing to present at Software Conferences in North America and Japan (the birthplace of Ruby) only. If you want to have this project presented elsewhere, like in Europe or South America, feel free to prepare and give your own presentations of the project, and if needed, hit me up for help on the [Glimmer Gitter chat](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge))
|
9
22
|
|
10
23
|
**Hello, World! Sample**
|
11
24
|
|
25
|
+
(Note: in real app development, we build [Glimmer Web Components](#hello-component), but this sample is just introducing basic building blocks towards building [components](#hello-component))
|
26
|
+
|
27
|
+
[lib/glimmer-dsl-web/samples/hello/hello_world.rb](/lib/glimmer-dsl-web/samples/hello/hello_world.rb)
|
28
|
+
|
12
29
|
Glimmer HTML DSL Ruby code in the frontend:
|
13
30
|
|
14
31
|
```ruby
|
@@ -37,8 +54,12 @@ You can also mount the `div` elsewhere by passing the `parent: parent_css_select
|
|
37
54
|
|
38
55
|
**Hello, Button!**
|
39
56
|
|
57
|
+
(Note: in real app development, we build [Glimmer Web Components](#hello-component), but this sample is just introducing basic building blocks towards building [components](#hello-component))
|
58
|
+
|
40
59
|
Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to JS global scope from Ruby to invoke functions like `alert`.
|
41
60
|
|
61
|
+
[lib/glimmer-dsl-web/samples/hello/hello_button.rb](/lib/glimmer-dsl-web/samples/hello/hello_button.rb)
|
62
|
+
|
42
63
|
Glimmer HTML DSL Ruby code in the frontend:
|
43
64
|
|
44
65
|
```ruby
|
@@ -71,8 +92,12 @@ Screenshot:
|
|
71
92
|
|
72
93
|
**Hello, Form!**
|
73
94
|
|
95
|
+
(Note: in real app development, we build [Glimmer Web Components](#hello-component), but this sample is just introducing basic building blocks towards building [components](#hello-component))
|
96
|
+
|
74
97
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby HTML DSL. Also, you can apply CSS styles by including directly in Ruby code as a string, using [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css), or managing CSS completely separately using something like [SCSS](https://sass-lang.com/). The CSS techniques could be combined as well, like by managing common reusable CSS styles separately in SCSS, but adding component specific CSS styles in Ruby when it is more convenient.
|
75
98
|
|
99
|
+
[lib/glimmer-dsl-web/samples/hello/hello_form.rb](/lib/glimmer-dsl-web/samples/hello/hello_form.rb)
|
100
|
+
|
76
101
|
Glimmer HTML DSL Ruby code in the frontend:
|
77
102
|
|
78
103
|
```ruby
|
@@ -227,8 +252,12 @@ Screenshot:
|
|
227
252
|
|
228
253
|
**Hello, Data-Binding!**
|
229
254
|
|
255
|
+
(Note: in real app development, we build [Glimmer Web Components](#hello-component), but this sample is just introducing basic building blocks towards building [components](#hello-component))
|
256
|
+
|
230
257
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) intuitively supports both Unidirectional (One-Way) Data-Binding via the `<=` operator and Bidirectional (Two-Way) Data-Binding via the `<=>` operator, incredibly simplifying how to sync View properties with Model attributes with the simplest code to reason about.
|
231
258
|
|
259
|
+
[lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb](/lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb)
|
260
|
+
|
232
261
|
Glimmer HTML DSL Ruby code in the frontend:
|
233
262
|
|
234
263
|
```ruby
|
@@ -344,10 +373,14 @@ Screenshot:
|
|
344
373
|
|
345
374
|
**Hello, Content Data-Binding!**
|
346
375
|
|
376
|
+
(Note: in real app development, we build [Glimmer Web Components](#hello-component), but this sample is just introducing basic building blocks towards building [components](#hello-component))
|
377
|
+
|
347
378
|
If you need to regenerate HTML element content dynamically, you can use Content Data-Binding to effortlessly
|
348
379
|
rebuild HTML elements based on changes in a Model attribute that provides the source data.
|
349
380
|
In this example, we generate multiple address forms based on the number of addresses the user has.
|
350
381
|
|
382
|
+
[lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb](/lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb)
|
383
|
+
|
351
384
|
Glimmer HTML DSL Ruby code in the frontend:
|
352
385
|
|
353
386
|
```ruby
|
@@ -487,6 +520,8 @@ Rails helper (more about it in [Hello, glimmer_component Rails Helper!](#hello-g
|
|
487
520
|
Below, we define an `AddressForm` component that generates an `address_form` keyword, and then we
|
488
521
|
reuse it twice inside an `AddressPage` component displaying a Shipping Address and a Billing Address.
|
489
522
|
|
523
|
+
[lib/glimmer-dsl-web/samples/hello/hello_component.rb](/lib/glimmer-dsl-web/samples/hello/hello_component.rb)
|
524
|
+
|
490
525
|
Glimmer HTML DSL Ruby code in the frontend:
|
491
526
|
|
492
527
|
```ruby
|
@@ -702,6 +737,8 @@ You may insert a Glimmer component anywhere into a Rails View using
|
|
702
737
|
`glimmer_component(component_path, *args)` Rails helper. Add `include GlimmerHelper` to `ApplicationHelper`
|
703
738
|
or another Rails helper, and use `<%= glimmer_component("path/to/component", *args) %>` in Views.
|
704
739
|
|
740
|
+
[lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb](/lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb)
|
741
|
+
|
705
742
|
Rails `ApplicationHelper` setup code:
|
706
743
|
|
707
744
|
```ruby
|
@@ -933,6 +970,8 @@ it returns a `String` to enable code like this:
|
|
933
970
|
|
934
971
|
In any case, below is a full example leveraging the Glimmer HTML DSL alternative approach when utilizing formatting elements underneath a paragraph.
|
935
972
|
|
973
|
+
[lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb](/lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb)
|
974
|
+
|
936
975
|
Glimmer HTML DSL Ruby code in the frontend:
|
937
976
|
|
938
977
|
```ruby
|
@@ -994,6 +1033,8 @@ Screenshot:
|
|
994
1033
|
|
995
1034
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) provides the `observe(model, attribute) { ... }` keyword to employ the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) as per [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (Model View Controller), enabling Views to observe Models and update themselves in response to changes. If the `observe` keyword is used from inside a [Component](#hello-component), when the Component is removed or its top-level element is removed, the observer is automatically cleaned up. The need for such explicit observers is significantly diminished by the availablility of the more advanced Unidirectional [Data-Binding](#hello-data-binding) Support and Bidirectional [Data-Binding](#hello-data-binding) Support.
|
996
1035
|
|
1036
|
+
[lib/glimmer-dsl-web/samples/hello/hello_observer.rb](/lib/glimmer-dsl-web/samples/hello/hello_observer.rb)
|
1037
|
+
|
997
1038
|
Glimmer HTML DSL Ruby code in the frontend:
|
998
1039
|
|
999
1040
|
```ruby
|
@@ -1017,48 +1058,81 @@ class HelloObserver
|
|
1017
1058
|
after_render do
|
1018
1059
|
@number_input.value = @number_holder.number
|
1019
1060
|
@range_input.value = @number_holder.number
|
1020
|
-
|
1021
|
-
#
|
1022
|
-
#
|
1061
|
+
|
1062
|
+
# Observe Model attribute @number_holder.number for changes and update View elements.
|
1063
|
+
# Observer is automatically cleaned up when `remove` method is called on rendered
|
1064
|
+
# HelloObserver web component or its top-level markup element (div)
|
1023
1065
|
observe(@number_holder, :number) do
|
1024
1066
|
number_string = @number_holder.number.to_s
|
1025
1067
|
@number_input.value = number_string unless @number_input.value == number_string
|
1026
1068
|
@range_input.value = number_string unless @range_input.value == number_string
|
1027
1069
|
end
|
1028
|
-
# Bidirectional Data-Binding does the same thing automatically
|
1029
|
-
# Just disable the observe block above as well as the oninput listeners below
|
1030
|
-
# and enable the `value <=> [@number_holder, :number]` lines to try the data-binding version
|
1031
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
1070
|
+
# Bidirectional Data-Binding does the same thing automatically as per alternative sample: Hello, Observer (Data-Binding)!
|
1032
1071
|
end
|
1033
1072
|
|
1034
1073
|
markup {
|
1035
1074
|
div {
|
1036
1075
|
div {
|
1037
1076
|
@number_input = input(type: 'number', min: 0, max: 100) {
|
1038
|
-
# oninput listener updates Model attribute @number_holder.number
|
1077
|
+
# oninput listener (observer) updates Model attribute @number_holder.number
|
1039
1078
|
oninput do
|
1040
1079
|
@number_holder.number = @number_input.value.to_i
|
1041
1080
|
end
|
1042
|
-
|
1043
|
-
# Bidirectional Data-Binding simplifies the implementation significantly
|
1044
|
-
# by enabling the following line and disabling oninput listeners as well
|
1045
|
-
# as the after_body observe block observer
|
1046
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
1047
|
-
# value <=> [@number_holder, :number]
|
1048
1081
|
}
|
1049
1082
|
}
|
1050
1083
|
div {
|
1051
1084
|
@range_input = input(type: 'range', min: 0, max: 100) {
|
1052
|
-
# oninput listener updates Model attribute @number_holder.number
|
1085
|
+
# oninput listener (observer) updates Model attribute @number_holder.number
|
1053
1086
|
oninput do
|
1054
1087
|
@number_holder.number = @range_input.value.to_i
|
1055
1088
|
end
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1089
|
+
}
|
1090
|
+
}
|
1091
|
+
}
|
1092
|
+
}
|
1093
|
+
end
|
1094
|
+
```
|
1095
|
+
|
1096
|
+
Screenshot:
|
1097
|
+
|
1098
|
+
![Hello, Observer!](/images/glimmer-dsl-web-samples-hello-hello-observer.gif)
|
1099
|
+
|
1100
|
+
**Hello, Observer (Data-Binding)!**
|
1101
|
+
|
1102
|
+
This is the data-binding edition of Hello, Observer!, which uses the `<=>` operator to perform bidirectional data-binding between a View property and a Model attribute, thus yield a lot less code that is declarative and is the most minimal code possible to express the requirements.
|
1103
|
+
|
1104
|
+
[lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb](/lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb)
|
1105
|
+
|
1106
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1107
|
+
|
1108
|
+
```ruby
|
1109
|
+
require 'glimmer-dsl-web'
|
1110
|
+
|
1111
|
+
class NumberHolder
|
1112
|
+
attr_accessor :number
|
1113
|
+
|
1114
|
+
def initialize
|
1115
|
+
self.number = 50
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
|
1119
|
+
class HelloObserver
|
1120
|
+
include Glimmer::Web::Component
|
1121
|
+
|
1122
|
+
before_render do
|
1123
|
+
@number_holder = NumberHolder.new
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
markup {
|
1127
|
+
div {
|
1128
|
+
div {
|
1129
|
+
input(type: 'number', min: 0, max: 100) {
|
1130
|
+
value <=> [@number_holder, :number]
|
1131
|
+
}
|
1132
|
+
}
|
1133
|
+
div {
|
1134
|
+
input(type: 'range', min: 0, max: 100) {
|
1135
|
+
value <=> [@number_holder, :number]
|
1062
1136
|
}
|
1063
1137
|
}
|
1064
1138
|
}
|
@@ -1100,7 +1174,9 @@ Learn more about the differences between various [Glimmer](https://github.com/An
|
|
1100
1174
|
- [Hello, World!](#hello-world)
|
1101
1175
|
- [Hello, Button!](#hello-button)
|
1102
1176
|
- [Hello, Form!](#hello-form)
|
1177
|
+
- [Hello, Form (MVP)!](#hello-form-mvp)
|
1103
1178
|
- [Hello, Observer!](#hello-observer)
|
1179
|
+
- [Hello, Observer (Data-Binding)!](#hello-observer)
|
1104
1180
|
- [Hello, Data-Binding!](#hello-data-binding)
|
1105
1181
|
- [Hello, Content Data-Binding!](#hello-content-data-binding)
|
1106
1182
|
- [Hello, Component!](#hello-content-data-binding)
|
@@ -1135,6 +1211,8 @@ You can setup Glimmer DSL for Web in [Rails 7](#rails-7), [Rails 6](#rails-6), o
|
|
1135
1211
|
|
1136
1212
|
### Rails 7
|
1137
1213
|
|
1214
|
+
(NOTE: In the future, we plan to automate the setup steps below. If you would like to help contribute that to the project, please do so and open a Pull Request.)
|
1215
|
+
|
1138
1216
|
Please follow these steps to setup.
|
1139
1217
|
|
1140
1218
|
Install a Rails 7 gem:
|
@@ -1152,7 +1230,7 @@ rails new glimmer_app_server
|
|
1152
1230
|
Add the following to `Gemfile`:
|
1153
1231
|
|
1154
1232
|
```
|
1155
|
-
gem 'glimmer-dsl-web', '~> 0.2.
|
1233
|
+
gem 'glimmer-dsl-web', '~> 0.2.6'
|
1156
1234
|
```
|
1157
1235
|
|
1158
1236
|
Run:
|
@@ -1354,6 +1432,8 @@ Next, read [Usage](#usage) instructions, and check out [Samples](#samples).
|
|
1354
1432
|
|
1355
1433
|
### Rails 6
|
1356
1434
|
|
1435
|
+
(NOTE: In the future, we plan to automate the setup steps below. If you would like to help contribute that to the project, please do so and open a Pull Request.)
|
1436
|
+
|
1357
1437
|
Please follow these steps to setup.
|
1358
1438
|
|
1359
1439
|
Install a Rails 6 gem:
|
@@ -1377,7 +1457,7 @@ Disable the `webpacker` gem line in `Gemfile`:
|
|
1377
1457
|
Add the following to `Gemfile`:
|
1378
1458
|
|
1379
1459
|
```ruby
|
1380
|
-
gem 'glimmer-dsl-web', '~> 0.2.
|
1460
|
+
gem 'glimmer-dsl-web', '~> 0.2.6'
|
1381
1461
|
```
|
1382
1462
|
|
1383
1463
|
Run:
|
@@ -1632,14 +1712,18 @@ This project is inspired by [Glimmer DSL for Opal](https://github.com/AndyObtiva
|
|
1632
1712
|
|
1633
1713
|
## Samples
|
1634
1714
|
|
1635
|
-
This external
|
1715
|
+
This external Sample Selector app is built using Rails and Glimmer DSL for Web, including all the samples mentioned below configured inside a Rails [Opal](https://opalrb.com/) web app with all the prerequisites ready to go for convenience (there is a very minimal [Standalone [No Rails] static site sample app](https://github.com/Largo/glimmer-dsl-web-standalone-demo) too):
|
1636
1716
|
|
1637
1717
|
https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app
|
1638
1718
|
|
1719
|
+
![Sample Selector](https://raw.githubusercontent.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/master/sample-glimmer-dsl-web-rails7-app.png)
|
1720
|
+
|
1639
1721
|
### Hello Samples
|
1640
1722
|
|
1641
1723
|
#### Hello, World!
|
1642
1724
|
|
1725
|
+
[lib/glimmer-dsl-web/samples/hello/hello_world.rb](/lib/glimmer-dsl-web/samples/hello/hello_world.rb)
|
1726
|
+
|
1643
1727
|
Glimmer HTML DSL Ruby code in the frontend:
|
1644
1728
|
|
1645
1729
|
```ruby
|
@@ -1692,6 +1776,8 @@ You can also mount the `div` elsewhere by passing the `parent: parent_css_select
|
|
1692
1776
|
|
1693
1777
|
Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to JS global scope from Ruby to invoke functions like `alert`.
|
1694
1778
|
|
1779
|
+
[lib/glimmer-dsl-web/samples/hello/hello_button.rb](/lib/glimmer-dsl-web/samples/hello/hello_button.rb)
|
1780
|
+
|
1695
1781
|
Glimmer HTML DSL Ruby code in the frontend:
|
1696
1782
|
|
1697
1783
|
```ruby
|
@@ -1726,6 +1812,8 @@ Screenshot:
|
|
1726
1812
|
|
1727
1813
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby HTML DSL. Also, you can apply CSS styles by including directly in Ruby code as a string, using [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css), or managing CSS completely separately using something like [SCSS](https://sass-lang.com/). The CSS techniques could be combined as well, like by managing common reusable CSS styles separately in SCSS, but adding component specific CSS styles in Ruby when it is more convenient.
|
1728
1814
|
|
1815
|
+
[lib/glimmer-dsl-web/samples/hello/hello_form.rb](/lib/glimmer-dsl-web/samples/hello/hello_form.rb)
|
1816
|
+
|
1729
1817
|
Glimmer HTML DSL Ruby code in the frontend:
|
1730
1818
|
|
1731
1819
|
```ruby
|
@@ -1878,10 +1966,63 @@ Screenshot:
|
|
1878
1966
|
|
1879
1967
|
![Hello, Form!](/images/glimmer-dsl-web-samples-hello-hello-form.gif)
|
1880
1968
|
|
1969
|
+
#### Hello, Form (MVP)!
|
1970
|
+
|
1971
|
+
This is the MVP (Model-View-Presenter) edition of Hello, Form! leveraging Glimmer Web Components and the MVP Architectural Pattern.
|
1972
|
+
|
1973
|
+
Main file:
|
1974
|
+
|
1975
|
+
[lib/glimmer-dsl-web/samples/hello/hello_form_mvp.rb](/lib/glimmer-dsl-web/samples/hello/hello_form_mvp.rb)
|
1976
|
+
|
1977
|
+
Other files:
|
1978
|
+
|
1979
|
+
[lib/glimmer-dsl-web/samples/hello/hello_form_mvp](/lib/glimmer-dsl-web/samples/hello/hello_form_mvp)
|
1980
|
+
|
1981
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1982
|
+
|
1983
|
+
```ruby
|
1984
|
+
require 'glimmer-dsl-web'
|
1985
|
+
|
1986
|
+
require_relative 'hello_form_mvp/presenters/hello_form_mvp_presenter'
|
1987
|
+
|
1988
|
+
require_relative 'hello_form_mvp/views/contact_form'
|
1989
|
+
require_relative 'hello_form_mvp/views/contact_table'
|
1990
|
+
|
1991
|
+
class HelloFormMvp
|
1992
|
+
include Glimmer::Web::Component
|
1993
|
+
|
1994
|
+
before_render do
|
1995
|
+
@presenter = HelloFormMvpPresenter.new
|
1996
|
+
end
|
1997
|
+
|
1998
|
+
markup {
|
1999
|
+
div {
|
2000
|
+
h1('Contact Form')
|
2001
|
+
|
2002
|
+
contact_form(presenter: @presenter)
|
2003
|
+
|
2004
|
+
h1('Contacts Table')
|
2005
|
+
|
2006
|
+
contact_table(presenter: @presenter)
|
2007
|
+
}
|
2008
|
+
}
|
2009
|
+
end
|
2010
|
+
|
2011
|
+
Document.ready? do
|
2012
|
+
HelloFormMvp.render
|
2013
|
+
end
|
2014
|
+
```
|
2015
|
+
|
2016
|
+
Screenshot:
|
2017
|
+
|
2018
|
+
![Hello, Form!](/images/glimmer-dsl-web-samples-hello-hello-form.gif)
|
2019
|
+
|
1881
2020
|
#### Hello, Observer!
|
1882
2021
|
|
1883
2022
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) provides the `observe(model, attribute) { ... }` keyword to employ the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) as per [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (Model View Controller), enabling Views to observe Models and update themselves in response to changes. If the `observe` keyword is used from inside a [Component](#hello-component), when the Component is removed or its top-level element is removed, the observer is automatically cleaned up. The need for such explicit observers is significantly diminished by the availablility of the more advanced Unidirectional [Data-Binding](#hello-data-binding) Support and Bidirectional [Data-Binding](#hello-data-binding) Support.
|
1884
2023
|
|
2024
|
+
[lib/glimmer-dsl-web/samples/hello/hello_observer.rb](/lib/glimmer-dsl-web/samples/hello/hello_observer.rb)
|
2025
|
+
|
1885
2026
|
Glimmer HTML DSL Ruby code in the frontend:
|
1886
2027
|
|
1887
2028
|
```ruby
|
@@ -1905,48 +2046,85 @@ class HelloObserver
|
|
1905
2046
|
after_render do
|
1906
2047
|
@number_input.value = @number_holder.number
|
1907
2048
|
@range_input.value = @number_holder.number
|
1908
|
-
|
1909
|
-
#
|
1910
|
-
#
|
2049
|
+
|
2050
|
+
# Observe Model attribute @number_holder.number for changes and update View elements.
|
2051
|
+
# Observer is automatically cleaned up when `remove` method is called on rendered
|
2052
|
+
# HelloObserver web component or its top-level markup element (div)
|
1911
2053
|
observe(@number_holder, :number) do
|
1912
2054
|
number_string = @number_holder.number.to_s
|
1913
2055
|
@number_input.value = number_string unless @number_input.value == number_string
|
1914
2056
|
@range_input.value = number_string unless @range_input.value == number_string
|
1915
2057
|
end
|
1916
|
-
# Bidirectional Data-Binding does the same thing automatically
|
1917
|
-
# Just disable the observe block above as well as the oninput listeners below
|
1918
|
-
# and enable the `value <=> [@number_holder, :number]` lines to try the data-binding version
|
1919
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
2058
|
+
# Bidirectional Data-Binding does the same thing automatically as per alternative sample: Hello, Observer (Data-Binding)!
|
1920
2059
|
end
|
1921
2060
|
|
1922
2061
|
markup {
|
1923
2062
|
div {
|
1924
2063
|
div {
|
1925
2064
|
@number_input = input(type: 'number', min: 0, max: 100) {
|
1926
|
-
# oninput listener updates Model attribute @number_holder.number
|
2065
|
+
# oninput listener (observer) updates Model attribute @number_holder.number
|
1927
2066
|
oninput do
|
1928
2067
|
@number_holder.number = @number_input.value.to_i
|
1929
2068
|
end
|
1930
|
-
|
1931
|
-
# Bidirectional Data-Binding simplifies the implementation significantly
|
1932
|
-
# by enabling the following line and disabling oninput listeners as well
|
1933
|
-
# as the after_body observe block observer
|
1934
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
1935
|
-
# value <=> [@number_holder, :number]
|
1936
2069
|
}
|
1937
2070
|
}
|
1938
2071
|
div {
|
1939
2072
|
@range_input = input(type: 'range', min: 0, max: 100) {
|
1940
|
-
# oninput listener updates Model attribute @number_holder.number
|
2073
|
+
# oninput listener (observer) updates Model attribute @number_holder.number
|
1941
2074
|
oninput do
|
1942
2075
|
@number_holder.number = @range_input.value.to_i
|
1943
2076
|
end
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
2077
|
+
}
|
2078
|
+
}
|
2079
|
+
}
|
2080
|
+
}
|
2081
|
+
end
|
2082
|
+
|
2083
|
+
Document.ready? do
|
2084
|
+
HelloObserver.render
|
2085
|
+
end
|
2086
|
+
```
|
2087
|
+
|
2088
|
+
Screenshot:
|
2089
|
+
|
2090
|
+
![Hello, Observer!](/images/glimmer-dsl-web-samples-hello-hello-observer.gif)
|
2091
|
+
|
2092
|
+
#### Hello, Observer (Data-Binding)!
|
2093
|
+
|
2094
|
+
This is the data-binding edition of Hello, Observer!, which uses the `<=>` operator to perform bidirectional data-binding between a View property and a Model attribute, thus yield a lot less code that is declarative and is the most minimal code possible to express the requirements.
|
2095
|
+
|
2096
|
+
[lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb](/lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb)
|
2097
|
+
|
2098
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
2099
|
+
|
2100
|
+
```ruby
|
2101
|
+
require 'glimmer-dsl-web'
|
2102
|
+
|
2103
|
+
class NumberHolder
|
2104
|
+
attr_accessor :number
|
2105
|
+
|
2106
|
+
def initialize
|
2107
|
+
self.number = 50
|
2108
|
+
end
|
2109
|
+
end
|
2110
|
+
|
2111
|
+
class HelloObserver
|
2112
|
+
include Glimmer::Web::Component
|
2113
|
+
|
2114
|
+
before_render do
|
2115
|
+
@number_holder = NumberHolder.new
|
2116
|
+
end
|
2117
|
+
|
2118
|
+
markup {
|
2119
|
+
div {
|
2120
|
+
div {
|
2121
|
+
input(type: 'number', min: 0, max: 100) {
|
2122
|
+
value <=> [@number_holder, :number]
|
2123
|
+
}
|
2124
|
+
}
|
2125
|
+
div {
|
2126
|
+
input(type: 'range', min: 0, max: 100) {
|
2127
|
+
value <=> [@number_holder, :number]
|
1950
2128
|
}
|
1951
2129
|
}
|
1952
2130
|
}
|
@@ -1966,6 +2144,8 @@ Screenshot:
|
|
1966
2144
|
|
1967
2145
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) intuitively supports both Unidirectional (One-Way) Data-Binding via the `<=` operator and Bidirectional (Two-Way) Data-Binding via the `<=>` operator, incredibly simplifying how to sync View properties with Model attributes with the simplest code to reason about.
|
1968
2146
|
|
2147
|
+
[lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb](/lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb)
|
2148
|
+
|
1969
2149
|
Glimmer HTML DSL Ruby code in the frontend:
|
1970
2150
|
|
1971
2151
|
```ruby
|
@@ -2139,6 +2319,8 @@ If you need to regenerate HTML element content dynamically, you can use Content
|
|
2139
2319
|
rebuild HTML elements based on changes in a Model attribute that provides the source data.
|
2140
2320
|
In this example, we generate multiple address forms based on the number of addresses the user has.
|
2141
2321
|
|
2322
|
+
[lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb](/lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb)
|
2323
|
+
|
2142
2324
|
Glimmer HTML DSL Ruby code in the frontend:
|
2143
2325
|
|
2144
2326
|
```ruby
|
@@ -2278,6 +2460,8 @@ Rails helper (more about it in [Hello, glimmer_component Rails Helper!](#hello-g
|
|
2278
2460
|
Below, we define an `AddressForm` component that generates an `address_form` keyword, and then we
|
2279
2461
|
reuse it twice inside an `AddressPage` component displaying a Shipping Address and a Billing Address.
|
2280
2462
|
|
2463
|
+
[lib/glimmer-dsl-web/samples/hello/hello_component.rb](/lib/glimmer-dsl-web/samples/hello/hello_component.rb)
|
2464
|
+
|
2281
2465
|
Glimmer HTML DSL Ruby code in the frontend:
|
2282
2466
|
|
2283
2467
|
```ruby
|
@@ -2493,6 +2677,8 @@ You may insert a Glimmer component anywhere into a Rails View using
|
|
2493
2677
|
`glimmer_component(component_path, *args)` Rails helper. Add `include GlimmerHelper` to `ApplicationHelper`
|
2494
2678
|
or another Rails helper, and use `<%= glimmer_component("path/to/component", *args) %>` in Views.
|
2495
2679
|
|
2680
|
+
[lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb](/lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb)
|
2681
|
+
|
2496
2682
|
Rails `ApplicationHelper` setup code:
|
2497
2683
|
|
2498
2684
|
```ruby
|
@@ -2724,6 +2910,8 @@ it returns a `String` to enable code like this:
|
|
2724
2910
|
|
2725
2911
|
In any case, below is a full example leveraging the Glimmer HTML DSL alternative approach when utilizing formatting elements underneath a paragraph.
|
2726
2912
|
|
2913
|
+
[lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb](/lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb)
|
2914
|
+
|
2727
2915
|
Glimmer HTML DSL Ruby code in the frontend:
|
2728
2916
|
|
2729
2917
|
```ruby
|
@@ -2785,6 +2973,8 @@ Screenshot:
|
|
2785
2973
|
|
2786
2974
|
#### Hello, Input (Date/Time)!
|
2787
2975
|
|
2976
|
+
[lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb](/lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb)
|
2977
|
+
|
2788
2978
|
Glimmer HTML DSL Ruby code in the frontend:
|
2789
2979
|
|
2790
2980
|
```ruby
|
@@ -2890,6 +3080,8 @@ Screenshot:
|
|
2890
3080
|
|
2891
3081
|
#### Button Counter
|
2892
3082
|
|
3083
|
+
[lib/glimmer-dsl-web/samples/regular/button_counter.rb](/lib/glimmer-dsl-web/samples/regular/button_counter.rb)
|
3084
|
+
|
2893
3085
|
Glimmer HTML DSL Ruby code in the frontend demonstrating MVC + Glimmer Web Components (Views) + Data-Binding:
|
2894
3086
|
|
2895
3087
|
```ruby
|
@@ -2992,11 +3184,40 @@ Learn more by reading the [GPG](https://github.com/AndyObtiva/glimmer/blob/maste
|
|
2992
3184
|
|
2993
3185
|
## Help
|
2994
3186
|
|
3187
|
+
### FAQ
|
3188
|
+
|
3189
|
+
F.A.Q. (Frequently Asked Questions):
|
3190
|
+
|
3191
|
+
**Can I reuse JavaScript libraries from Glimmer DSL for Web in Ruby?**
|
3192
|
+
|
3193
|
+
Absolutely. Glimmer DSL for Web can integrate with any JavaScript libraries. You can either load the JavaScript libraries in advance by linking to them in the Rails View/Layout (e.g. linking to JS library CDN URLs) or by including JavaScript files in the lookup directories of Opal Ruby, and adding a Ruby `require('path_to_js_lib')` call in the code. In Ruby, the `$$` global variable gives access to the top-level JavaScript global scope, which enables invocations on any JavaScript objects. For example, `$$.hljs` gives access to the loaded `window.hljs` object for the Highlight.js library, and that enables invoking any functions from that library as needed, like `$$.hljs.highlightAll` to activate code syntax highlighting.
|
3194
|
+
|
3195
|
+
**How does Glimmer DSL for Web compare to Rails Hotwire (Turbo)?**
|
3196
|
+
|
3197
|
+
Glimmer DSL for Web is a Frontend library, meaning it replaces the JavaScript layer in a web application (e.g. Rails app) with Ruby code. On the other hand, Rails Hotwire (Turbo) is mostly a Backend-driven technology that enables automatically replacing HTML DOM elements with HTML markup sent over the wire from a Rails Backend. So, the two technologies are mostly orthogonal, but can be used in the same Rails web application, albeit exclusively on separate web pages at the moment. In the future, we might explore supporting the ability to combine both technologies in the same pages, but until then, use on separate pages. Glimmer DSL for Web can handle any sort of Frontend interactions even without making HTTP calls to the Backend, so it can implement more use-cases than Hotwire. Using Glimmer DSL for Web with Rails API end-points is simpler than using Hotwire overall. That is because Glimmer Content Data-Binding is a simpler version of Turbo Frames that does not require worrying about setting and using element IDs (as that is handled automatically) and that operates at a more correct abstraction level for how we think about View component updates in relation to Model changes (we make updates at the Model layer, and they automatically get reflected in the View through data-binding). Also, Glimmer DSL for Web supports Glimmer Web Components, which enable better division and organization of View code into modular components than ERB plus having higher readability. It is true that Hotwire is an improvement over using JavaScript frameworks like React when there is not much logic beyond updating elements with Server-Side rendered HTML. And, Glimmer DSL for Web is the next big advancement that provides an even simpler approach while also giving you full Frontend Development capabilities using Ruby in the Browser.
|
3198
|
+
|
3199
|
+
**How does Glimmer DSL for Web compare to Phlex or ViewComponent?**
|
3200
|
+
|
3201
|
+
Glimmer DSL for Web is a Frontend library, meaning it replaces the JavaScript layer in a web application (e.g. Rails app) with Ruby code while providing its own View-layer component support using [`Glimmer::Web::Component`](#hello-component). On the other hand, Phlex and ViewComponent are Backend View-layer component libraries, so they serve 100% orthogonal needs, and can be used side by side with Glimmer DSL for Web if needed (e.g. Phlex components can consist of Backend HTML elements + Glimmer components that are rendered in the Frontend). That said, Phlex came out years after previous Glimmer libraries like Glimmer DSL for SWT, and Phlex's component system is very similar to Glimmer's component system in Glimmer DSL for SWT (perhaps inspired by it unconsciously or consciously). So, if you like Phlex in the Backend, you'll love Glimmer DSL for Web in the Frontend.
|
3202
|
+
|
3203
|
+
**How does Glimmer DSL for Web compare to Angular, React, Vue, Svelte, or other JS frameworks?**
|
3204
|
+
|
3205
|
+
Without delving into details, Glimmer DSL for Web is meant to be a Ruby-based drop-in replacement for Angular, React, Vue, Svelte, and other JS frameworks. Additionally, it enables writing both structure code and logic code in the same language (Ruby), greatly simplifying maintainability and improving productivity by eliminating multi-language dissonance and friction that drags down productivity as there is no need anymore to think in multiple languages unnecessarily, use XML based solutions (e.g. JSX), or use templating solutions (e.g. Mustache). Lastly, Glimmer DSL for Web supports familiar Software Engineering architectural patterns like Model-View-Controller and Model-View-Presenter, enabling Software Engineers to write the lightest and simplest code possible for building Web frontends in Ruby, with the best separation of concerns. Software Engineers can finally become happy Ruby developers by writing Ruby code in the Frontend too now in addition to the Backend.
|
3206
|
+
|
3207
|
+
**How do I have a Glimmer Web Component re-render in a similar way to how React components re-render?**
|
3208
|
+
|
3209
|
+
[Content Data-Binding](#hello-content-data-binding) supports re-rendering dynamic parts of a Glimmer Web Component (or the full component if all of it is dynamic). Glimmer DSL for Web simplifies Frontend Development significantly over React by not re-rendering everything if not needed (regardless of use of Virtual DOM) yet only re-rendering the parts of a component that do change dynamically. As a result, Software Engineers do not have to worry about the ripple effect of full re-renders or the possibility of breaking some parts of a page when making small changes to a single component in a hierarchy of page components. And, if only an element property changes, [Content Data-Binding](#hello-content-data-binding) is not even needed. It is much simpler to rely on simple [Property Data-Binding](#hello-data-binding) in that case. This makes reasoning about Glimmer DSL for Web Ruby code a lot simpler than reasoning about React component JavaScript code.
|
3210
|
+
|
3211
|
+
**How do I reuse React components from Glimmer DSL for Web?**
|
3212
|
+
|
3213
|
+
In the future, support for HTML Web Components will be added, and that will enable reuse of React components by using a library that converts them to HTML Web Components first like [react-to-web-component](https://github.com/bitovi/react-to-web-component) or [react-webcomponent](https://github.com/adobe/react-webcomponent).
|
3214
|
+
|
3215
|
+
|
2995
3216
|
### Issues
|
2996
3217
|
|
2997
|
-
You may submit [issues](https://github.com/AndyObtiva/glimmer-dsl-web
|
3218
|
+
You may submit [issues](https://github.com/AndyObtiva/glimmer-dsl-web/issues) on [GitHub](https://github.com/AndyObtiva/glimmer-dsl-web/issues).
|
2998
3219
|
|
2999
|
-
[Click here to submit an issue.](https://github.com/AndyObtiva/glimmer-dsl-web
|
3220
|
+
[Click here to submit an issue.](https://github.com/AndyObtiva/glimmer-dsl-web/issues)
|
3000
3221
|
|
3001
3222
|
### Chat
|
3002
3223
|
|
@@ -3020,7 +3241,7 @@ These features have been suggested. You might see them in a future version of Gl
|
|
3020
3241
|
|
3021
3242
|
* [Andy Maleh](https://github.com/AndyObtiva) (Founder)
|
3022
3243
|
|
3023
|
-
[Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer-dsl-web
|
3244
|
+
[Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer-dsl-web/graphs/contributors)
|
3024
3245
|
|
3025
3246
|
## License
|
3026
3247
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.6
|
data/glimmer-dsl-web.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer-dsl-web 0.2.
|
5
|
+
# stub: glimmer-dsl-web 0.2.6 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-web".freeze
|
9
|
-
s.version = "0.2.
|
9
|
+
s.version = "0.2.6".freeze
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Andy Maleh".freeze]
|
14
|
-
s.date = "2024-
|
15
|
-
s.description = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) enables building Web Frontends using Ruby in the Browser, as per Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with DSLs and TIMTOWTDI) and the Rails way (Convention over Configuration) in building Isomorphic Ruby on Rails Applications. It provides a Ruby HTML DSL, which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using <=>). Dynamic rendering (and re-rendering) of HTML content is also supported via Content Data-Binding.
|
14
|
+
s.date = "2024-05-26"
|
15
|
+
s.description = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) enables building Web Frontends using Ruby in the Browser, as per Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with DSLs and TIMTOWTDI) and the Rails way (Convention over Configuration) in building Isomorphic Ruby on Rails Applications. It provides a Ruby HTML DSL, which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using <=>). Dynamic rendering (and re-rendering) of HTML content is also supported via Content Data-Binding. Modular design is supported with Glimmer Web Components. And, a Ruby CSS DSL is supported with the included Glimmer DSL for CSS. Many samples are demonstrated in the Rails sample app (there is a very minimal Standalone [No Rails] sample app too). You can finally live in pure Rubyland on the Web in both the frontend and backend with Glimmer DSL for Web! This gem relies on Opal Ruby.".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.extra_rdoc_files = [
|
18
18
|
"CHANGELOG.md",
|
@@ -36,9 +36,15 @@ Gem::Specification.new do |s|
|
|
36
36
|
"lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb",
|
37
37
|
"lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb",
|
38
38
|
"lib/glimmer-dsl-web/samples/hello/hello_form.rb",
|
39
|
+
"lib/glimmer-dsl-web/samples/hello/hello_form_mvp.rb",
|
40
|
+
"lib/glimmer-dsl-web/samples/hello/hello_form_mvp/models/contact.rb",
|
41
|
+
"lib/glimmer-dsl-web/samples/hello/hello_form_mvp/presenters/hello_form_mvp_presenter.rb",
|
42
|
+
"lib/glimmer-dsl-web/samples/hello/hello_form_mvp/views/contact_form.rb",
|
43
|
+
"lib/glimmer-dsl-web/samples/hello/hello_form_mvp/views/contact_table.rb",
|
39
44
|
"lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb",
|
40
45
|
"lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb",
|
41
46
|
"lib/glimmer-dsl-web/samples/hello/hello_observer.rb",
|
47
|
+
"lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb",
|
42
48
|
"lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb",
|
43
49
|
"lib/glimmer-dsl-web/samples/hello/hello_world.rb",
|
44
50
|
"lib/glimmer-dsl-web/samples/regular/button_counter.rb",
|
@@ -70,24 +76,24 @@ Gem::Specification.new do |s|
|
|
70
76
|
]
|
71
77
|
s.homepage = "http://github.com/AndyObtiva/glimmer-dsl-web".freeze
|
72
78
|
s.licenses = ["MIT".freeze]
|
73
|
-
s.rubygems_version = "3.
|
79
|
+
s.rubygems_version = "3.5.3".freeze
|
74
80
|
s.summary = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework)".freeze
|
75
81
|
|
76
82
|
s.specification_version = 4
|
77
83
|
|
78
|
-
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6"])
|
79
|
-
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.
|
80
|
-
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.
|
81
|
-
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2"])
|
82
|
-
s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3"])
|
83
|
-
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1"])
|
84
|
-
s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1"])
|
85
|
-
s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1", "< 3.0.0"])
|
86
|
-
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 0"])
|
87
|
-
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
|
88
|
-
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
|
89
|
-
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9", "< 3.0.0"])
|
90
|
-
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
|
91
|
-
s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2"])
|
84
|
+
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6".freeze])
|
85
|
+
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0".freeze])
|
86
|
+
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.4.0".freeze])
|
87
|
+
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2".freeze])
|
88
|
+
s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3".freeze])
|
89
|
+
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1".freeze])
|
90
|
+
s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1".freeze])
|
91
|
+
s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1".freeze, "< 3.0.0".freeze])
|
92
|
+
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 0".freeze])
|
93
|
+
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0".freeze, "< 14.0.0".freeze])
|
94
|
+
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0".freeze])
|
95
|
+
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9".freeze, "< 3.0.0".freeze])
|
96
|
+
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1".freeze, "< 7.0.0".freeze])
|
97
|
+
s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2".freeze])
|
92
98
|
end
|
93
99
|
|
@@ -49,6 +49,7 @@ module Glimmer
|
|
49
49
|
def_option_attr_accessors(new_options)
|
50
50
|
end
|
51
51
|
end
|
52
|
+
alias attributes options
|
52
53
|
|
53
54
|
def option(new_option, default: nil)
|
54
55
|
new_option = new_option.to_s.to_sym
|
@@ -58,6 +59,7 @@ module Glimmer
|
|
58
59
|
'def_option_attr_accessors(new_options)'
|
59
60
|
def_option_attr_accessors(new_options)
|
60
61
|
end
|
62
|
+
alias attribute option
|
61
63
|
|
62
64
|
def def_option_attr_accessors(new_options)
|
63
65
|
new_options.each do |option, default|
|
@@ -22,6 +22,7 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
24
|
module ::Kernel
|
25
|
+
# TODO contribute to Opal
|
25
26
|
alias puts_without_glimmer puts
|
26
27
|
def puts(*strs)
|
27
28
|
puts_without_glimmer(*strs)
|
@@ -31,6 +32,7 @@ module ::Kernel
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
# TODO contribute to Opal
|
34
36
|
alias p_without_glimmer p
|
35
37
|
def p(*args)
|
36
38
|
p_without_glimmer(*args)
|
@@ -23,6 +23,8 @@ require 'glimmer-dsl-web'
|
|
23
23
|
|
24
24
|
include Glimmer
|
25
25
|
|
26
|
+
# This is an introductory version of Hello, Form!
|
27
|
+
# Check out Hello, Form (MVP)! for a more serious advanced version built with Glimmer Web Components.
|
26
28
|
Document.ready? do
|
27
29
|
div {
|
28
30
|
h1('Contact Form')
|
@@ -0,0 +1 @@
|
|
1
|
+
Contact = Struct.new(:name, :email, keyword_init: true)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../models/contact'
|
2
|
+
|
3
|
+
class HelloFormMvpPresenter
|
4
|
+
attr_accessor :contacts
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@contacts = fetch_contacts
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch_contacts
|
11
|
+
[
|
12
|
+
Contact.new(name: 'John Doe', email: 'johndoe@example.com'),
|
13
|
+
Contact.new(name: 'Jane Doe', email: 'janedoe@example.com'),
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
def new_contact
|
18
|
+
@new_contact ||= Contact.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_contact
|
22
|
+
contacts << Contact.new(name: new_contact.name, email: new_contact.email)
|
23
|
+
new_contact.name = new_contact.email = ''
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class ContactForm
|
2
|
+
include Glimmer::Web::Component
|
3
|
+
|
4
|
+
option :presenter
|
5
|
+
|
6
|
+
markup {
|
7
|
+
form {
|
8
|
+
div {
|
9
|
+
label('Name: ', for: 'name-field')
|
10
|
+
@name_input = input(type: 'text', id: 'name-field', required: true, autofocus: true) {
|
11
|
+
value <=> [presenter.new_contact, :name]
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
div {
|
16
|
+
label('Email: ', for: 'email-field')
|
17
|
+
@email_input = input(type: 'email', id: 'email-field', required: true) {
|
18
|
+
value <=> [presenter.new_contact, :email]
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
div {
|
23
|
+
input(type: 'submit', value: 'Add Contact') {
|
24
|
+
onclick do |event|
|
25
|
+
if [@name_input, @email_input].all?(&:check_validity)
|
26
|
+
event.prevent_default
|
27
|
+
# adding contact model to presenter contacts array indirectly updates contacts table
|
28
|
+
presenter.add_contact
|
29
|
+
@name_input.focus
|
30
|
+
end
|
31
|
+
end
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
style {
|
36
|
+
# CSS can be included as Glimmer DSL for CSS syntax (Ruby code)
|
37
|
+
r('input') {
|
38
|
+
margin '5px'
|
39
|
+
}
|
40
|
+
r('input[type=submit]') {
|
41
|
+
margin '5px 0'
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class ContactTable
|
2
|
+
include Glimmer::Web::Component
|
3
|
+
|
4
|
+
option :presenter
|
5
|
+
|
6
|
+
markup {
|
7
|
+
table {
|
8
|
+
thead {
|
9
|
+
tr {
|
10
|
+
th('Name')
|
11
|
+
th('Email')
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
tbody {
|
16
|
+
content(presenter, :contacts) {
|
17
|
+
presenter.contacts.each do |contact|
|
18
|
+
tr {
|
19
|
+
td(contact.name)
|
20
|
+
td(contact.email)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
style {
|
27
|
+
# CSS can be included as Glimmer DSL for CSS syntax (Ruby code)
|
28
|
+
r('table') {
|
29
|
+
border '1px solid grey'
|
30
|
+
border_spacing '0'
|
31
|
+
}
|
32
|
+
r('table tr td, table tr th') {
|
33
|
+
padding '5px'
|
34
|
+
}
|
35
|
+
r('table tr:nth-child(even)') {
|
36
|
+
background '#ccc'
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright (c) 2023-2024 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer-dsl-web'
|
23
|
+
|
24
|
+
require_relative 'hello_form_mvp/presenters/hello_form_mvp_presenter'
|
25
|
+
|
26
|
+
require_relative 'hello_form_mvp/views/contact_form'
|
27
|
+
require_relative 'hello_form_mvp/views/contact_table'
|
28
|
+
|
29
|
+
class HelloFormMvp
|
30
|
+
include Glimmer::Web::Component
|
31
|
+
|
32
|
+
before_render do
|
33
|
+
@presenter = HelloFormMvpPresenter.new
|
34
|
+
end
|
35
|
+
|
36
|
+
markup {
|
37
|
+
div {
|
38
|
+
h1('Contact Form')
|
39
|
+
|
40
|
+
contact_form(presenter: @presenter)
|
41
|
+
|
42
|
+
h1('Contacts Table')
|
43
|
+
|
44
|
+
contact_table(presenter: @presenter)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
Document.ready? do
|
50
|
+
HelloFormMvp.render
|
51
|
+
end
|
@@ -39,48 +39,34 @@ class HelloObserver
|
|
39
39
|
after_render do
|
40
40
|
@number_input.value = @number_holder.number
|
41
41
|
@range_input.value = @number_holder.number
|
42
|
-
|
43
|
-
#
|
44
|
-
#
|
42
|
+
|
43
|
+
# Observe Model attribute @number_holder.number for changes and update View elements.
|
44
|
+
# Observer is automatically cleaned up when `remove` method is called on rendered
|
45
|
+
# HelloObserver web component or its top-level markup element (div)
|
45
46
|
observe(@number_holder, :number) do
|
46
47
|
number_string = @number_holder.number.to_s
|
47
48
|
@number_input.value = number_string unless @number_input.value == number_string
|
48
49
|
@range_input.value = number_string unless @range_input.value == number_string
|
49
50
|
end
|
50
|
-
# Bidirectional Data-Binding does the same thing automatically
|
51
|
-
# Just disable the observe block above as well as the oninput listeners below
|
52
|
-
# and enable the `value <=> [@number_holder, :number]` lines to try the data-binding version
|
53
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
51
|
+
# Bidirectional Data-Binding does the same thing automatically as per alternative sample: Hello, Observer (Data-Binding)!
|
54
52
|
end
|
55
53
|
|
56
54
|
markup {
|
57
55
|
div {
|
58
56
|
div {
|
59
57
|
@number_input = input(type: 'number', min: 0, max: 100) {
|
60
|
-
# oninput listener updates Model attribute @number_holder.number
|
58
|
+
# oninput listener (observer) updates Model attribute @number_holder.number
|
61
59
|
oninput do
|
62
60
|
@number_holder.number = @number_input.value.to_i
|
63
61
|
end
|
64
|
-
|
65
|
-
# Bidirectional Data-Binding simplifies the implementation significantly
|
66
|
-
# by enabling the following line and disabling oninput listeners as well
|
67
|
-
# as the after_body observe block observer
|
68
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
69
|
-
# value <=> [@number_holder, :number]
|
70
62
|
}
|
71
63
|
}
|
72
64
|
div {
|
73
65
|
@range_input = input(type: 'range', min: 0, max: 100) {
|
74
|
-
# oninput listener updates Model attribute @number_holder.number
|
66
|
+
# oninput listener (observer) updates Model attribute @number_holder.number
|
75
67
|
oninput do
|
76
68
|
@number_holder.number = @range_input.value.to_i
|
77
69
|
end
|
78
|
-
|
79
|
-
# Bidirectional Data-Binding simplifies the implementation significantly
|
80
|
-
# by enabling the following line and disabling oninput listeners as well
|
81
|
-
# as the after_body observe block observer
|
82
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
83
|
-
# value <=> [@number_holder, :number]
|
84
70
|
}
|
85
71
|
}
|
86
72
|
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright (c) 2023-2024 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer-dsl-web'
|
23
|
+
|
24
|
+
class NumberHolder
|
25
|
+
attr_accessor :number
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
self.number = 50
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class HelloObserver
|
33
|
+
include Glimmer::Web::Component
|
34
|
+
|
35
|
+
before_render do
|
36
|
+
@number_holder = NumberHolder.new
|
37
|
+
end
|
38
|
+
|
39
|
+
markup {
|
40
|
+
div {
|
41
|
+
div {
|
42
|
+
input(type: 'number', min: 0, max: 100) {
|
43
|
+
value <=> [@number_holder, :number]
|
44
|
+
}
|
45
|
+
}
|
46
|
+
div {
|
47
|
+
input(type: 'range', min: 0, max: 100) {
|
48
|
+
value <=> [@number_holder, :number]
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
Document.ready? do
|
56
|
+
HelloObserver.render
|
57
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -30,28 +30,28 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.4.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
40
|
+
version: 1.4.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: glimmer-dsl-css
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.
|
47
|
+
version: 1.4.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
54
|
+
version: 1.4.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: opal
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,11 +240,11 @@ description: Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) en
|
|
240
240
|
both structure code and logic code in one language. It supports both Unidirectional
|
241
241
|
(One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using
|
242
242
|
<=>). Dynamic rendering (and re-rendering) of HTML content is also supported via
|
243
|
-
Content Data-Binding.
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
Ruby.
|
243
|
+
Content Data-Binding. Modular design is supported with Glimmer Web Components. And,
|
244
|
+
a Ruby CSS DSL is supported with the included Glimmer DSL for CSS. Many samples
|
245
|
+
are demonstrated in the Rails sample app (there is a very minimal Standalone [No
|
246
|
+
Rails] sample app too). You can finally live in pure Rubyland on the Web in both
|
247
|
+
the frontend and backend with Glimmer DSL for Web! This gem relies on Opal Ruby.
|
248
248
|
email: andy.am@gmail.com
|
249
249
|
executables: []
|
250
250
|
extensions: []
|
@@ -269,9 +269,15 @@ files:
|
|
269
269
|
- lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb
|
270
270
|
- lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb
|
271
271
|
- lib/glimmer-dsl-web/samples/hello/hello_form.rb
|
272
|
+
- lib/glimmer-dsl-web/samples/hello/hello_form_mvp.rb
|
273
|
+
- lib/glimmer-dsl-web/samples/hello/hello_form_mvp/models/contact.rb
|
274
|
+
- lib/glimmer-dsl-web/samples/hello/hello_form_mvp/presenters/hello_form_mvp_presenter.rb
|
275
|
+
- lib/glimmer-dsl-web/samples/hello/hello_form_mvp/views/contact_form.rb
|
276
|
+
- lib/glimmer-dsl-web/samples/hello/hello_form_mvp/views/contact_table.rb
|
272
277
|
- lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb
|
273
278
|
- lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb
|
274
279
|
- lib/glimmer-dsl-web/samples/hello/hello_observer.rb
|
280
|
+
- lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb
|
275
281
|
- lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb
|
276
282
|
- lib/glimmer-dsl-web/samples/hello/hello_world.rb
|
277
283
|
- lib/glimmer-dsl-web/samples/regular/button_counter.rb
|
@@ -319,7 +325,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
319
325
|
- !ruby/object:Gem::Version
|
320
326
|
version: '0'
|
321
327
|
requirements: []
|
322
|
-
rubygems_version: 3.
|
328
|
+
rubygems_version: 3.5.3
|
323
329
|
signing_key:
|
324
330
|
specification_version: 4
|
325
331
|
summary: Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework)
|