|
1 | 1 | # Component Concept |
2 | 2 |
|
3 | | -Show [specs](/spec/usage/base/component_spec.rb) |
| 3 | +Show [specs](/spec/usage/base/component_spec.rb). |
4 | 4 |
|
5 | | -A component is used to define reusable UI elements. This documentation enables anyone to write custom components that live within a Rails application. All custom components need a *prefixed 'custom_'* to be referenced within the `app/matestack/` folder in a Rails application. |
| 5 | +Components are used to define reusable UI elements. The `matestack-ui-core` contains a number of generic, so-called `core components`, but anyone can extend them and write `custom components` that live within a his or her application and cater a specific or unique need. |
6 | 6 |
|
7 | | -To extend the available core components, feel free to fork this repo and create them within the `app/concepts` folder, analogous to the existing core components. |
| 7 | +This document aims to give a brief introducing to the different kinds of components (with links to further sources) and serves as a manual on [how to configure your components](#component-configuration). |
8 | 8 |
|
9 | | -In the beginning, static components are introduced. Later, dynamic components follow by integrating Vue.js. After that, all the configuration options for Matestack components get explained! |
| 9 | +## Core Components |
10 | 10 |
|
11 | | -## Static components |
| 11 | +See [here](/docs/components/README.md) for a list of available `core components`. In general, they are separated into HTML-only **static** components and **dynamic** components that come with Javascript-powered, dynamic behaviour. |
12 | 12 |
|
13 | | -All static components inherit from the `Matestack::Ui::StaticComponent` class and get rendered without any javascript involved. |
| 13 | +If you miss a component that you think we're missing in the `core components` right now, [create an issue](https://github.com/basemate/matestack-ui-core/issues/new) in our GitHub! |
14 | 14 |
|
15 | | -### A simple static component |
| 15 | +If you have created your own component and feel like it would be a great addition to the `core components`, please [create a pull request](https://github.com/basemate/matestack-ui-core/compare) including tests and documentation. |
16 | 16 |
|
17 | | -Define the component in `app/matestack/components/component1.rb` like so |
| 17 | +To extend the available core components, just fork [the repo](https://github.com/basemate/matestack-ui-core) and create them within the `app/concepts` folder, analogous to the existing core components - and you're always invited to reach out to [our community](https://gitter.im/basemate/community) if you face any problems! |
18 | 18 |
|
19 | | -```ruby |
20 | | -class Components::Component1 < Matestack::Ui::StaticComponent |
21 | | - |
22 | | - def response |
23 | | - components { |
24 | | - div id: "my-component" do |
25 | | - plain "I'm a static component!" |
26 | | - end |
27 | | - } |
28 | | - end |
29 | | - |
30 | | -end |
31 | | -``` |
32 | | - |
33 | | -and add it to the response part of an Example Page that lives somewhere in `app/matestack/pages/example_app/example_page.rb` |
34 | | - |
35 | | -```ruby |
36 | | -class Pages::ExamplePage < Matestack::Ui::Page |
37 | | - |
38 | | - def response |
39 | | - components { |
40 | | - div id: "div-on-page" do |
41 | | - # below is the reference to the custom component |
42 | | - custom_component1 |
43 | | - end |
44 | | - } |
45 | | - end |
46 | | - |
47 | | -end |
48 | | -``` |
49 | | - |
50 | | -This will get rendered into |
51 | | - |
52 | | -```html |
53 | | -<div id="div-on-page"> |
54 | | - <div id="my-component"> |
55 | | - I'm a static component! |
56 | | - </div> |
57 | | -</div> |
58 | | -``` |
59 | | - |
60 | | -### Multiple components may live in one namespace |
61 | | - |
62 | | -Define the first component in `app/matestack/components/namespace1/component1.rb` |
63 | | - |
64 | | -```ruby |
65 | | -class Components::Namespace1::Component1 < Matestack::Ui::StaticComponent |
66 | | - |
67 | | - def response |
68 | | - components { |
69 | | - div class: "my-component" do |
70 | | - plain "I'm a static component!" |
71 | | - end |
72 | | - } |
73 | | - end |
74 | | - |
75 | | -end |
76 | | -``` |
77 | | - |
78 | | -and define a second component in the same namespace: `app/matestack/components/namespace1/component2.rb` |
79 | | - |
80 | | -```ruby |
81 | | -class Components::Namespace1::Component2 < Matestack::Ui::StaticComponent |
82 | | - |
83 | | - def response |
84 | | - components { |
85 | | - div class: "my-component-2" do |
86 | | - plain "I'm a second custom static component!" |
87 | | - end |
88 | | - } |
89 | | - end |
90 | | - |
91 | | -end |
92 | | -``` |
93 | | - |
94 | | -then add both components to the response part of the Example Page in `app/matestack/pages/example_page.rb` |
95 | | - |
96 | | -```ruby |
97 | | -class Pages::ExamplePage < Matestack::Ui::Page |
98 | | - |
99 | | - def response |
100 | | - components { |
101 | | - div id: "div-on-page" do |
102 | | - custom_namespace1_component1 |
103 | | - custom_namespace1_component2 |
104 | | - end |
105 | | - } |
106 | | - end |
107 | | - |
108 | | -end |
109 | | -``` |
110 | | - |
111 | | -The output looks like this: |
112 | | - |
113 | | -```html |
114 | | -<div id="div-on-page"> |
115 | | - <div class="my-component-1"> |
116 | | - I'm a static component! |
117 | | - </div> |
118 | | - <div class="my-component-2"> |
119 | | - I'm a second custom static component! |
120 | | - </div> |
121 | | -</div> |
122 | | -``` |
123 | | - |
124 | | -### Camelcased module or class names |
125 | | - |
126 | | -Components named in camelcase are referenced to with their downcased counterpart! |
127 | | -As an example, define the camelcased component in `app/matestack/components/my_component.rb` |
128 | | - |
129 | | -```ruby |
130 | | -class Components::MyComponent < Matestack::Ui::StaticComponent |
131 | | - |
132 | | - def response |
133 | | - components { |
134 | | - div id: "my-component" do |
135 | | - plain "I'm a static component!" |
136 | | - end |
137 | | - } |
138 | | - end |
139 | | - |
140 | | -end |
141 | | -``` |
142 | | - |
143 | | -and add it to the response part of the Example Page (`app/matestack/pages/example_page.rb`, remember?) via *downcased reference* |
144 | | - |
145 | | -```ruby |
146 | | -class Pages::ExamplePage < Matestack::Ui::Page |
147 | | - |
148 | | - def response |
149 | | - components { |
150 | | - div id: "div-on-page" do |
151 | | - # if my_component was called, this would refer to Components::My::Component |
152 | | - # and woulnd't deliver the desired outcome |
153 | | - custom_myComponent |
154 | | - end |
155 | | - } |
156 | | - end |
157 | | - |
158 | | -end |
159 | | -``` |
160 | | - |
161 | | -As expected, it will get rendered into |
| 19 | +## Custom Components |
162 | 20 |
|
163 | | -```html |
164 | | -<div id="div-on-page"> |
165 | | - <div id="my-component-1"> |
166 | | - I'm a static component! |
167 | | - </div> |
168 | | -</div> |
169 | | -``` |
170 | | - |
171 | | -## Dynamic components |
172 | | - |
173 | | -So far, all custom components were static ones. Reminder: All components that inherit from `Matestack::Ui::StaticComponent` get rendered without any javascript involved. But static components can also be wrapped inside dynamic components to create, well, dynamic behavior! |
174 | | - |
175 | | -### Async wrapper to add basic dynamic behavior |
176 | | - |
177 | | -Create a custom *static* component in `app/matestack/components/static/component.rb` |
178 | | - |
179 | | -```ruby |
180 | | -class Components::Static::Component < Matestack::Ui::StaticComponent |
181 | | - |
182 | | - def response |
183 | | - components { |
184 | | - div id: "my-component" do |
185 | | - plain "I'm a static component!" |
186 | | - plain DateTime.now.strftime('%Q') |
187 | | - end |
188 | | - } |
189 | | - end |
190 | | - |
191 | | -end |
192 | | -``` |
193 | | - |
194 | | -and add it to the Example Page, wrapping it into an *async component* to make it *dynamic*! The *async component* is a core component and therefore does not need a *custom_* prefix. |
195 | | - |
196 | | -```ruby |
197 | | -class Pages::ExamplePage < Matestack::Ui::Page |
198 | | - |
199 | | - def response |
200 | | - components { |
201 | | - div id: "div-on-page" do |
202 | | - async rerender_on: "my_event" do |
203 | | - custom_some_component |
204 | | - end |
205 | | - end |
206 | | - } |
207 | | - end |
208 | | - |
209 | | -end |
210 | | -``` |
211 | | - |
212 | | -Now, the page will respond with static content, but our component rerenders (visible by looking at the timestamp) whenever *"my_event"* happens. This event may be triggered by all kinds of other components, for example a `onclick` component: |
213 | | - |
214 | | -```ruby |
215 | | -class Pages::ExamplePage < Matestack::Ui::Page |
216 | | - |
217 | | - def response |
218 | | - components { |
219 | | - div id: "div-on-page" do |
220 | | - onclick emit "my_event" |
221 | | - |
222 | | - async rerender_on: "my_event" do |
223 | | - custom_some_component |
224 | | - end |
225 | | - end |
226 | | - } |
227 | | - end |
228 | | - |
229 | | -end |
230 | | -``` |
231 | | - |
232 | | -### Dynamic components with custom Vue.js |
233 | | - |
234 | | -To create a custom dynamic component, create an associated file such as `app/matestack/components/dynamic/component.rb`. |
235 | | - |
236 | | - |
237 | | -In contrast to static components that inherit from `Matestack::Ui::StaticComponent`, a custom dynamic component inherits from *a different class*, `Matestack::Ui::DynamicComponent`: |
238 | | - |
239 | | -```ruby |
240 | | -class Dynamic::Component < Matestack::Ui::DynamicComponent |
241 | | - |
242 | | - def response |
243 | | - components { |
244 | | - div id: "my-component" do |
245 | | - plain "I'm a fancy dynamic component! Call me {{dynamic_value}}!" |
246 | | - end |
247 | | - } |
248 | | - end |
249 | | - |
250 | | -end |
251 | | -``` |
252 | | - |
253 | | -The JavaScript part is defined in `app/matestack/components/dynamic/component.js` as a Vue.js component: |
254 | | - |
255 | | -```javascript |
256 | | -MatestackUiCore.Vue.component('dynamic-component-cell', { |
257 | | - mixins: [MatestackUiCore.componentMixin], |
258 | | - data: function data() { |
259 | | - return { |
260 | | - dynamic_value: "foo" |
261 | | - }; |
262 | | - }, |
263 | | - mounted(){ |
264 | | - const self = this |
265 | | - setTimeout(function () { |
266 | | - self.dynamic_value = "bar" |
267 | | - }, 300); |
268 | | - } |
269 | | -}); |
270 | | -``` |
| 21 | +By definition, `custom components` only live within your application. In Rails applications, they are put into the `app/matestack/components/` directory. To use them on your `apps` and `pages`, you need to add a *prefixed 'custom_'*. This clearly differentiates them from the vanilla `core components`. |
271 | 22 |
|
272 | | -**Important:** You need to add this `component.js` to your `application.js`: |
| 23 | +### Static Components |
273 | 24 |
|
274 | | -`app/assets/javascripts/application.js` |
| 25 | +See [here](/docs/extend/custom_static_components.md) for an extensive guide on creating your own `custom static components`. Orchestrate existing `core components` to avoid repetition, or get creative and add your own `HAML` templates! |
275 | 26 |
|
276 | | -```javascript |
277 | | -//... |
278 | | - |
279 | | -//= require matestack-ui-core |
280 | | - |
281 | | -//... |
282 | | - |
283 | | -//= require dynamic/component |
284 | | - |
285 | | -//... |
286 | | - |
287 | | -``` |
| 27 | +### Dynamic Components |
288 | 28 |
|
289 | | -And if not already done: |
| 29 | +See [here](/docs/extend/custom_dynamic_components.md) for an extensive guide on creating your own `custom dynamic components`. Those allow you to extend and create rich user exeriences by writing custom Vue.Js! |
290 | 30 |
|
291 | | -`config/initializers/assets.rb` |
292 | | - |
293 | | -```ruby |
294 | | -Rails.application.config.assets.paths << Rails.root.join('app/matestack/components') |
295 | | -``` |
296 | | - |
297 | | -Add the dynamic component to an example page the same way it is done with static components: |
298 | | - |
299 | | -```ruby |
300 | | -class Pages::ExamplePage < Matestack::Ui::Page |
301 | | - |
302 | | - def response |
303 | | - components { |
304 | | - div id: "div-on-page" do |
305 | | - custom_dynamic_component |
306 | | - end |
307 | | - } |
308 | | - end |
309 | | - |
310 | | -end |
311 | | -``` |
312 | | - |
313 | | -On initial pageload, this is the HTML received: |
314 | | - |
315 | | -```html |
316 | | -<div id="div-on-page"> |
317 | | - <div id="my-component"> |
318 | | - I'm a fancy dynamic component! Call me foo! |
319 | | - </div> |
320 | | -</div> |
321 | | -``` |
| 31 | +### Actionview Components |
322 | 32 |
|
323 | | -And after 300ms, *foo* changes into *bar* dynamically - magic! |
| 33 | +See [here](/docs/extend/custom_actionview_component.md) for a guide on creating custom `actionview components`, both `static` and `dynamic`. Those allow you to harness the power of various Rails `ActionView` helpers without including them in your `custom components`. |
324 | 34 |
|
325 | 35 | ## Component configuration |
326 | 36 |
|
327 | | -See below for an overview of the various possibilities Matestack provides for component configuration, both for custom and core components! |
| 37 | +See below for an overview of the various possibilities Matestack provides for component configuration, both for `custom components` and `core components`! |
328 | 38 |
|
329 | 39 | ### Passing options to components |
330 | 40 |
|
|
0 commit comments