# General Component API

See below for an overview of the various possibilities Matestack provides for component implementation:

## Response

Use the `response` method to define the UI of the component by using other components.

```ruby
  class Some::Component < Matestack::Ui::Component

    def response
      div id: "my-component" do
        plain "hello world!"
      end
    end

  end
```

```ruby
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
      some_component
    end
  end

end
```

This is the HTML which gets created:

```markup
<div id="div-on-page">
  <div id="my-component">
    hello world!
  </div>
</div>
```

If no `response` method is defined, matestack will look for a corresponding `HAML` template file lying next to Ruby component file.

## Prepare

Use a prepare method to resolve data before rendering a component!

```ruby
  class Some::Component < Matestack::Ui::Component

    def prepare
      @some_data = "some data"
    end

    def response
      div id: "my-component" do
        plain @some_data
      end
    end

  end
```

```ruby
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
      some_component
    end
  end

end
```

This is the HTML which gets created:

```markup
<div id="div-on-page">
  <div id="my-component">
    some data
  </div>
</div>
```

The prepare method comes in handy to read from the database or to resolve content before displaying it!

## Params access

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

```ruby
class Some::Component < Matestack::Ui::Component

  def response
    div id: "my-component" do
      plain params[:foo]
    end
  end

end
```

On the example page, reference the component as usual.

```ruby
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
      some_component
    end
  end

end
```

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:

```markup
<div id="div-on-page">
  <div id="my-component">
    bar
  </div>
</div>
```

## Passing options to components

### Define optional and required properties

Matestack components give you the option to define required and optional properties for a component. It creates helpers for these properties automatically.

#### Requires

Required properties are required for your component to work, like the name suggests. If at least one required property is missing a `Matestack::Ui::Core::Properties::PropertyMissingException` is raised.

Declare your required properties by calling `requires` as follows:

```ruby
class SomeComponent < Matestack::Ui::Component

  requires :some_property, :some_other

end
```

You then can use these properties simply by calling the provided helper method, which is generated for you. The helper method name corresponds to the passed property name.

```ruby
class SomeComponent < Matestack::Ui::Component

  requires :some_property, :some_other

  def response
    # display some_property plain inside a div and some_other property inside a paragraph beneath it
    div do
      plain some_property
    end
    paragraph text: some_other
  end

end
```

#### Optional

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

```ruby
class SomeComponent < Matestack::Ui::Component

  optional :optional_property, :other_optional_property  optional properties could be empty

  def response
    # display optional_property plain inside a div and other_optional_property property inside a paragraph beneath it
    div do
      plain optional_property
    end
    paragraph text: other_optional_property
  end

end
```

#### Passing properties to components

Pass the properties as a hash directly to the component when calling it. You can pass any object you like and use it in the component with the helper.

```ruby
class SomeComponent < Matestack::Ui::Component

  requires :some_option,
  optional :some_other  optional properties could be empty

  def response
    div do
      plain some_option
    end
    if some_other.present?
      paragraph text: some_other[:option]
    end
  end

end
```

Use it in the example page and pass in the properties as a hash

```ruby
class ExamplePage < Matestack::Ui::Page

  def prepare
    @hello = "hello!"
  end

  def response
    div id: "div-on-page" do
      some_component some_option: @hello, some_other: { option: "world!" }
    end
  end

end
```

The outcome is quite as expected:

```markup
<div id="div-on-page">
  <div>
    hello!
  </div>
  <p>world!</p>
</div>
```

#### Alias properties

Matestack tries to prevent overriding existing methods while creating helpers. If you pass a property with a name that matches any instance method of your component matestack will raise a `Matestack::Ui::Core::Properties::PropertyOverwritingExistingMethodException`. To use property names that would raise this exception, simply provide an alias name with the `as:` option. You can then use the alias accordingly.

```ruby
class SomeComponent < Matestack::Ui::Component
  requires :foo, :bar, method: { as: :my_method }
  optional response: { as: :my_response }

  def response
    div do
      plain "#{foo} - #{bar} - #{my_method}"  string concatenation of properties foo, bar, and method aliased as my_method
    end
    paragraph my_response if my_response.present?  response property aliased as my_response inside a paragraph if it is present
  end
end
```

Some common names that could not be used as properties:

```ruby
:method,
:params
```

## Arguments

If no hash was given, a component can also access/accept a simple argument!

```ruby
class Components::Some::Component < Matestack::Ui::Component

  def response
    div id: "my-component" do
      plain @argument
    end
  end

end
```

Just make sure to pass an argument on the example page:

```ruby
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
       simply pass a string here
      some_component "foo from page"
    end
  end

end
```

No miracle to find here, just what was expected!

```markup
<div id="div-on-page">
  <div id="my-component">
    foo from page
  </div>
</div>
```

## Yielding inside components

Components can yield a block with access to scope, where a block is defined. This works the way *yield* usually works in Ruby. But make sure to explicitly call *'yield\_components'* within the component response!

```ruby
class Some::Component < Matestack::Ui::Component

  def response
    div id: "my-component" do
      yield_components
    end
  end

end
```

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

```ruby
class ExamplePage < Matestack::Ui::Page

  def prepare
    @foo = "foo from page"
  end

  def response
    div id: "div-on-page" do
      some_component do
        plain @foo
      end
    end
  end

end
```

Not a fancy example, but this is the result:

```markup
<div id="div-on-page">
  <div id="my-component">
    foo from page
  </div>
</div>
```

## Partials

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:

```ruby
class Some::Component < Matestack::Ui::Component

  def response
    div id: "my-component" do
      my_partial "foo from component"
    end
  end

  def my_partial text
    plain text
  end

end
```

As everything is already defined in the component, calling the `some_component` on the example page is all there is to do:

```ruby
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
      custom_some_component
    end
  end

end
```

The outcome is the usual, boring HTML response. Below the HTML snippet, a more exciting example of partial usage is waiting!

```markup
<div id="div-on-page">
  <div id="my-component">
    foo from component
  </div>
</div>
```

### Modules: Partials on steriods!

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

```ruby
module MySharedPartials

  def my_partial text
    plain text
  end

end
```

Include the module in the component:

```ruby
class Some::Component < Matestack::Ui::Component

  include MySharedPartials

  def response
    div id: "my-component" do
      my_partial "foo from component"
    end
  end

end
```

Then reference the component on the example page as before:

```ruby
class ExamplePage < Matestack::Ui::Page

  def response
    div id: "div-on-page" do
      some_component
    end
  end

end
```

The output is unspectacular in this example, but more complex codebases will greatly benefit from this refactoring option!

```markup
<div id="div-on-page">
  <div id="my-component">
    foo from component
  </div>
</div>
```

Try combining partials with options and slots (see below) for maximum readability, dryness and fun!

## Slots

Similar to named slots in Vue.js, slots in Matestack allows 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.

```ruby
class Some::Component < Matestack::Ui::Component

  requires :slots

  def prepare
    @foo = "foo from component"
  end

  def response
    div id: "my-component" do
      slot slots[:my_first_slot]
      br
      slot slots[:my_second_slot]
    end
  end

end
```

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

```ruby
class ExamplePage < Matestack::Ui::Page

  def prepare
    @foo = "foo from page"
  end

  def response
    div do
      some_component slots: {
        my_first_slot: my_simple_slot,
        my_second_slot: my_second_simple_slot
      }
    end
  end

  def my_simple_slot
    slot do
      span id: "my_simple_slot" do
        plain "some content"
      end
    end
  end

  def my_second_simple_slot
    slot do
      span id: "my_simple_slot" do
        plain @foo
      end
    end
  end

end
```

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

```markup
<div>
  <div id="my-component">
    <span id="my_simple_slot">
      some content
    </span>
    <br/>
    <span id="my_simple_slot">
      foo from page
    </span>
  </div>
</div>
```

### Using slots of components within components

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

```ruby
class Other::Component < Matestack::Ui::Component

  requires :slots

  def prepare
    @foo = "foo from other component"
  end

  def response
    div id: "my-other-component" do
      slot slots[:my_slot_from_component]
      br
      slot slots[:my_slot_from_page]
      br
      plain @foo
    end
  end

end
```

and also in some component:

```ruby
class Some::Component < Matestack::Ui::Component

  requires :slots

  def prepare
    @foo = "foo from component"
  end

  def response
    div id: "my-component" do
      other_component slots: {
        my_slot_from_component: my_slot_from_component,
        my_slot_from_page: slots[:my_slot_from_page]
      }
    end
  end

  def my_slot_from_component
    slot do
      span id: "my-slot-from-component" do
        plain @foo
      end
    end
  end

end
```

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:

```ruby
class ExamplePage < Matestack::Ui::Page

  def prepare
    @foo = "foo from page"
  end

  def response
    div id: "page-div" do
      some_component slots: { my_slot_from_page: my_slot_from_page }
    end
  end

  def my_slot_from_page
    slot do
      span id: "my-slot-from-page" do
        plain @foo
      end
    end
  end

end
```

This gets rendered into the HTML below:

```markup
<div id="page-div">
  <div id="my-component">
    <div id="my-other-component">
      <span id="my-slot-from-component">
        foo from component
      </span>
      <br/>
      <span id="my-slot-from-page">
        foo from page
      </span>
      <br/>
      foo from other component
    </div>
  </div>
</div>
```

This may seem complicated at first, but it can provide valuable freedom of configuration and great fallbacks in more complex scenarios!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.matestack.io/matestack-ui-core/1.5.0/ui-components/general-component-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
