|
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