API

Response

Use the response method to define the UI of the component by using Matestack's HTML rendering or calling components.

  class SomeComponent < Matestack::Ui::Component

    def response
      div id: "my-component" do
        plain "hello world!"
      end
      SomeOtherComponent.()
    end

  end
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
      SomeComponent.()
    end
  end

end

Partials and helper methods

Use partials to keep the code dry and indentation layers manageable!

Local partials on component level

In the component definition, see how this time from inside the response, the my_partial method below is called:

Partials defined in modules

Extract code snippets to modules for an even better project structure. First, create a module:

Include the module in the component:

Helper methods

Not only can instance methods be used as "partials" but as general helpers performing any kind of logic or data resolving:

Render?

Use the render? method to conditionally render the component based on custom rules:

This is particularly useful to avoid plastering your views with conditional statements like if and unless.

Instead of:

You can just use:

Prepare

Use a prepare method to resolve instance variables before rendering a component if required.

This is the HTML which gets created:

Params access

A component can access request information, e.g. url query params, by calling the params method:

On the example page, reference the component as usual.

Now, visiting the respective route to the page, e.g. via /xyz?foo=bar, the component reads the [:foo] from the params and displays it like so:

Passing data to components

You often need to pass data into your component to make them reusable. You have multiple possibilities to do that:

General options access

If you pass in a hash to a component...

...this hash is accessible via options in the component:

Optional and required options

Matestack components give you the possibility to define an explicit API for your component describing required and optional options for a component. Using this approach, it's way easier to understand what data can be processed by your component.

required and optional options will be deleted from the options hash and are only available via the context object.

Required options

Required options are required for your component to work, like the name suggests. If at least one required option is missing, an Exception is raised.

Declare your required options by calling required as follows:

You then can use these options simply by calling the provided OpenStruct object context, which includes the injected options with their name:

Optional options

To define optional options you can use the same syntax as required. Just use optional instead of required. Optional options are optional and not validated for presence like required options.

Passing more complex data structures to components

You can pass any object you like and use it in the component with the helper.

Use it in the example page and pass in one option as a hash

Alias properties

It's not possible to overwrite core methods of the OpenStruct object context

If you somehow want to inject options with a key matching a core method of the OpenStruct object, simply provide an alias name with the as: option. You can then use the alias accordingly. A popular example would be the option called class

Text argument

Sometimes you just want to pass in a simple (text) argument rather than a hash with multiple keys:

A component can access this text argument in various ways:

This approach can be combined with injecting Hashes to components:

Yielding inside components

Components can yield a block with access to scope, where a block is defined.

Pass a block to a component on the page as shown below:

Not a fancy example, but this is the result:

Slots

Slots in Matestack allow us to inject whole UI snippets into the component. It's a more specific yielding mechanism as you will yield multiple "named blocks" into the component. Each of these blocks can be referenced and positioned independently in the component,

Slots on the page instance scope

Define the slots within the component file as shown below. Please make sure to inject slots within a hash slots: { ... } into the component.

Slots have access to the scope of the class, where they are defined. In this case @foo

This gets rendered into HTML as shown below. Notice that the @foo from the component configuration got overwritten by the page's local @foo!

Using slots of components within components

To use component instance scope slots, first define slots within a static component:

and also in some component:

Then, put both components (note that some component uses other component so that's how they're both in here) to use on the example page:

This gets rendered into the HTML below:

Calling slots with params

Sometimes it's necessary to call a slot with params:

Last updated

Was this helpful?