Essential Guide 7: Partials and custom components
Demo: Matestack Demo Github Repo: Matestack Demo Application
Welcome to the seventh part of our tutorial about building a web application with matestack.
Introduction
In this part, we will discover how we can create custom components with matestack to declutter and better structure our code.
In this guide, we will
refactor our new and edit forms with partials
refactor our person index page with components
refactor the show page and reuse our component
add a custom component to our app
Prerequisites
We expect you to have successfully finished the previous guide.
Using partials
Partials are an easy way to structure code in apps, pages and components. Let's take a look at how partials work with an example, changing our first page.
Partials can be used to split view code apart, in order to write better structurem, more readable, cleaner code. As we can see in the example, a partial is nothing else but a method call. The method implements a view part. Partials can also be used within partials.
Now we know what partials can do, lets refactor our person new and edit pages. They share a lot of same code, both containing the same form. To reuse our code, we create a Demo::Pages::Person::Form
page, from which both new and edit will inherit. Let's create it in app/matestack/demo/pages/persons/form.rb
Now we have a form page, which only implements a partial person_form
containing the new and edit form for our person. It takes one parameter, which will be used as the button label, in order to allow different labels for new and edit. We know from an earlier chapter, that a form needs a hash as parameter. Our person_form_config
method should return the config hash. As this hash changes, depending on the page we use our form, we need to overwrite it in the class where we inherit from our form.
First we refactor our new page. We change it, so it inherits from our form page, replace the form with the partial and rename the method returning the form config hash to match the name of our form page.
Our new page looks now much cleaner. We overwrite person_form_config
, which is used in the partial as an input for the required hash parameter of the form, setting the correct configurations for our new form.
After this we can refactor our edit page accordingly. Inherit from our form page, use the form partial and overwrite the config method.
We successfully refactored our code using partials, so it's better structured, more readable and we keep it dry (don't repeat yourself).
Visit localhost:3000 and navigate to the new and edit pages, to check that everything works like before.
Custom components
Custom components can be used to create reusable components, representing ui parts. They can be just a button, or a more complex card or even a complete slider, which reuses the card component.
In the next steps we want to refactor our person index page, by creating a person teaser component.
But first, we need to create a component registry. Every custom components need to be registered through a component registry. It is possible to use multiple registries to keep for example admin components apart from public components, but in this guide we keep it simple and only use one registry. Let's create it in app/matestack/components/registry.rb
. As our components should be reusable by all apps, pages and components, we create them in the app/matestack/components
folder, where our registry lives.
In the above registry, we registered a person_teaser
component, which refers to the class Components::Person::Teaser
. Let's implement this class, our first component, in app/matestack/components/persons/teaser.rb
.
Let's take a look whats happening in our component. Components need to inherit from matestacks component Matestack::Ui::Component
. They also define a response method, which contains the content that is rendered. As we want to display information from a person, we need access to a person in our component. To achieve this components offer you the possibility to define required and optional properties with the requires
and optional
methods. We can pass as many symbols as we like to one of the calls or call it multiple times. Every so defined property is accessible through a method with the same name as the symbol. In the response
we create a div containing a h3 tag with the full name of the person, a transition to the show page and the delete button we also had on the index page.
In order to use this our teaser component we need to include the component registry in the ApplicationController
.
Now we can use our custom person teaser by calling person_teaser
to refactor our list of person on our index page. Instead of iterating over the persons and creating a list element for every person, we now can iterate over the persons and call our component passing the person to it.
Using our custom component is as easy as calling the name we defined in our registry. Required and optional propertys are passed to a component as a hash. If we would not provide a person to our person teaser the component would raise an exception as a person is required. Optional properties are as the name suggests optional and therefore can be left out.
When you start your application locally now, the missing list bullet points should be the only visible change. We will take care of styling soon - but first, let's reuse our newly introduced component!
Using HAML in custom components
If you need more fine-grained control of your view layer or want to reuse some old HAML files, you can also create custom components like this:
Create a file called app/matestack/components/person/disclaimer.rb
and add this content:
Since this component does not have a response
method, matestack automatically looks for a disclaimer.haml
file right next to the component. Note that you can still use a prepare
method.
So let's add the disclaimer.haml
file in app/matestack/components/person/
and add a simple paragraph:
To display this disclaimer on every page within our Demo::App
, we need to register it in the /app/matestack/components/registry.rb
:
Afterwards, add it to app/matestack/demo/app.rb
within the main
-block:
Different from our person_teaser
, we don't need to hand over properties to our person_disclaimer
. Spin up your application and check out the changes!
More information on custom components
Even though we only covered very basic cases here, you may already have some idea of how powerful custom components can be! By leveraging useful namespaces and calling custom components within other custom components, you can get quite fancy and build complex user interfaces while keeping the code maintainable and reasonable.
Side note: Custom components also give you a neat way of reusing your *.haml
views with matestack (erb and slim support will be added soon).
To learn more, check out the basic building blocks guides section about custom components.
Saving the status quo
As usual, we want to commit the progress to Git. In the repo root, run
Recap & outlook
Today, we covered a great way of extracting recurring UI elements into reusable components with matestack. Of course, we only covered a very basic use case here and there are various ways of using custom components.
Take a well deserved rest and make sure to come back to the next part of this series, introducing the powerful collection
component.
Last updated