############################################
Refactoring Into Components
############################################
It is possible to write the entire code and all the elements inside one big file. But this would create a file that is hard to maintain. It is better to break up the code into several pieces. This way you get an app that is better to maintain and you gain reusable code, leading to less repetitions. In Ember, these pieces are called components.
There are two kinds of compoenents, built-in components and custom components. You already encountered a built-in component when you created the form: the ```` component. In the most basic form, you call a component simply by its name like you would with a regular HTML-element ````. You can see it is a component, since it uses the naming convention known as "PascalCase". According to this convention the name is capitalized and if it made of compound words every new word is capitalized as well. A component's name is derived from the name of its file. We'll cover this file in a minute.
When creating custom components, you should think about, what you want to do with them. There are two different kinds of components. Template components and components with component class or "glimmer components", since they extend the component class of ``glimmer``. The former is used for presenting information to the user, the latter also implements logic in form of a JavaScript file. Either way, you create a component by running
.. code-block:: console
$ yarn ember generate component my-awesome-component
This will create a template componentthat you can call as ```` inside your templates. After running the code above, your terminal will give you the following feedback
.. code-block:: console
installing component
create app/components/my-awesome-component.hbs
skip app/components/my-awesome-component.js
tip to add a class, run `ember generate component-class my-awesome-component`
installing component-test
create tests/integration/components/my-awesome-component.js
informing you that the template file and a test file have been created. You do not need to use the test file, since you can use other automatic test programs, like ``cypress`` what we use in the exercises. It also tells you that the JavaScript file has not been created but that you can do so, if you should need it. If you know, that you are going to need the file, you can add the ``-gc`` or ``--with-component-class`` flag when creating the component:
.. code-block:: console
$ yarn ember g component amazing-glimmer-component -gc
This time, you will be informed that three files have been created:
.. code-block:: console
installing component
create app/components/amazing-glimmer-component.js
create app/components/amazing-glimmer-component.hbs
installing component-test
create tests/integration/components/amazing-glimmer-component.js
Component Classes
------------------
Since we want to implement logic, we want to utilize the latter way of creating a component. Inside your terminal, enter the following:
.. code-block:: console
$ yarn ember generate component login-page -gc
Like all components, it will be created inside the ``app/components`` folder. Next, cut everything besides ``{{page-title "Login"}}`` from ``app/routes/login.hbs`` and paste it into ``app/components/login-page.hbs``. Invoke the component in the oute template via ```` in the second line.
.. warning::
If you do not invoke the component in the template but leave everything in the template, your app will not work and throw an error instead, saying that you try to access variables out of scope.
In the template we used two variables ``email`` and ``password``. Update the ``app/components/login-page.js`` to define the two variables as properties on the component class:
.. code-block:: js
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
export default class LoginPageComponent extends Component {
@tracked email = '';
@tracked password = '';
};
Note the new import statement. By this we can monitor the properites of the marked variables and know if they change and act accordingly. You will see that this has no effect, as the two properties are both empty. However, now try setting a value to either the ``email`` or ``password`` property and you will see that those are reflected in the interface when the application rebuilds and reloads.
We can test that the input element is actually tied to the property on the controller and in that way see one of the real benefits of using a framework such as Ember. Update the two ``