- Open Step 1 in StackBlitz
-
Right click on the
app/folder to get the context menu. In this menu, select to generate a new "Component". -
When prompted for the component name, type
add-childand press the ENTER key.You should see a new
.scssand.tsfile under theadd-child/folder now. However, the component doesn't show in the app preview to the right. -
This is because we need to hook the component up to the router. Open
/src/app-routing.module.ts. -
We need to add the component to a route and import the component into the module. Add the following import and update the routes as seen below.
import { AddChildComponent } from './add-child/add-child.component'; const routes: Routes = [ {path: '', component: AddChildComponent}, {path: 'add', component: AddChildComponent} ];
The routes are examined in order, the first match is activated and following matches are ignored. The route with an empty path represents the app's root route (i.e. https://rapid-mvp-workshop.firebaseapp.com/). This means that our home page will now display the new
AddChildComponent. The second route here also makes this component available at/add. This is useful in case we change the default route. We'll still have a valid route to theAddChildComponent.You should see "add-child Works!" in your app preview.
-
Now we need to make this add child component do something useful. The first thing that it needs to do is allow the user to select the gender of the child. We'll do this using a couple cards. Let's add the boy card and some containers (for layout) first:
In
/src/app/add-child.component.tschange thetemplateto:template: ` <div class="container" fxLayout="column" fxLayoutAlign="start center"> <div id="genderSelection" fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="center center" fxLayoutGap="24px" fxFlex> <mat-card id="boy" (click)="addBoy()" aria-label="Add a boy"> <mat-card-content fxLayout="row" fxLayoutAlign="center center"> </mat-card-content> <mat-card-actions align="end"> <button mat-button color="primary">Add a boy</button> </mat-card-actions> </mat-card> </div> </div> `,
In
/src/app/add-child.component.scssadd the following::host { display: flex; height: 100%; width: 100%; } .container { margin-top: 24px; width: 100%; #genderSelection { width: 100%; margin-bottom: 48px; .mat-card { width: 192px; cursor: pointer; } } }
You should now see a card with a flat button for "Add a boy".
First, take note of how the card is built. There is a
mat-cardparent that can contain a number of card elements likemat-card-contentandmat-card-actions. We take advantage of themat-card-actionsAPI here to align the button at the end (right side in a RTL or Right To Left locale). You can find out more aboutmat-cardand its elements on its docs page. There you can see thatalign="start"is the other option format-card-actionsbutton alignment.We make the card clickable by adding a
clickevent handler. Angular uses a shorthand for these event handlers by surrounding the event name with parenthesis. This supports native events or custom events. We'll add thisaddBoy()function later. For interactive elements that aren't native elements (like<button>), you'll want to add a usefularia-labelto support accessibility (a11y).We're using a
mat-buttonas well. This component uses a nativebuttonelement in order to gain all of the benefits of native buttons (a11y, default behaviors/styles, etc.). Additionally, we use thecolor="primary"theme API. This is common across most all of the Angular Material components. It tells the component weather it should use the primary, accent, or warn palette.Now you are probably wonder what all of these
fx*attributes are all about. These are part of the Angular Flex Layout library. For now, the interesting Flex Layout attributes are ongenderSelection:fxLayout="column" fxLayout.gt-sm="row" fxLayoutAlign="center center" fxLayoutGap="24px" fxFlex. The first two fxLayout attributes tell the component to use a column layout by default, but when on screens that are greater than small, use a row layout. See the fxLayout docs for more details.The size definitions of the screens can be found in Flex Layout's Responsive API docs.
The fxFlex attribute indicates that this component should "Resize to fill the available space along the main-axis flow of its parent container." In a row layout, the main-axis would be horizontal. There are a lot of details in the fxFlex docs. It is highly recommended that you review them, even if you don't fully understand it all. If you want to better grasp Flexbox CSS Layouts, then I would recommend checking out Flexbox Zombies after this workshop.
Note that Flex Layout attributes without
Layoutin them, apply to the element itself. Flex Layout attributes withLayoutin them, apply to the children of the element.The fxLayoutAlign attribute here is indicating that the children of this component should be aligned in the center of the main axis and the center of the cross axis. The reason that this uses the axis terminology is because these axes can change when the layout changes from row to column and vice versa. So it can't just be vertically and horizontally. See the fxLayoutAlign docs for more details.
Finally, fxLayoutGap here tells the system to add a margin of
24pxbetween elements in this layout. This automatically accounts for row vs column layouts. See the fxLayoutGap docs for more details.Just one note about the SCSS that we added. We're using a special
:hostpseudo selector here. This allows styling the element that hosts the component, rather than some child element within the component. You can learn more in the Angular's Component Stying Docs.Now if you are starting to understand how Flex Layouts are supposed to work, you should be wondering why your new card isn't centered! doh! This is actually a very common issue. The attributes don't cause any build errors or failures if the module and library aren't included in the app! In Step 0, we only imported the library via NPM. However, we didn't register the module with Angular.
-
Add the
FlexLayoutModuleto your imports in/src/app/app.module.ts:imports: [ FlexLayoutModule, ],
-
Add the TypeScript import at the top of the
/src/app/app.module.tsfile:import { FlexLayoutModule } from '@angular/flex-layout';
Hooray! Your card should now be centered!
-
Now we'll add the card for selecting a girl. In
/src/app/add-child.component.tsadd the following thetemplateafter the end of the boy card:<mat-card id="girl" (click)="addGirl()" aria-label="Add a girl"> <mat-card-content fxLayout="row" fxLayoutAlign="center center"> </mat-card-content> <mat-card-actions align="end"> <button mat-button color="accent">Add a girl</button> </mat-card-actions> </mat-card>
Nothing special here. You should see a second card for adding a girl with a button that uses the
accentpalette. If the screen is larger than small (959px), then you should see two cards side by side. If the screen is small or smaller, then you should see one card above another card. You can use Chrome DevTools device mode to emulate this and test different size screens.
Now that we've got our first component created. We need to step back a little bit and do some optimizations so that our future workflow will be more efficient.
Here's the completed Step 1 on StackBlitz if you run into any problems.
