Skip to content

Instantly share code, notes, and snippets.

@mlabieniec
Last active November 30, 2021 19:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mlabieniec/821356ddc5cbf19124601981a23b12e3 to your computer and use it in GitHub Desktop.
Save mlabieniec/821356ddc5cbf19124601981a23b12e3 to your computer and use it in GitHub Desktop.
<div class="container">
<mat-sidenav-container
fullscreen
[hasBackdrop]="mobileQuery.matches">
<mat-sidenav #lnav
mode="over"
class="sidenav">
<div class="content">
<mat-list>
<mat-list-item *ngFor="let route of nav">
<a mat-button routerLink="{{route.path}}" routerLinkActive="active" (click)="toggleMobileNav(lnav)">{{route.title}}</a>
</mat-list-item>
</mat-list>
</div>
</mat-sidenav>
<mat-sidenav-content class="sidenav-content">
<mat-toolbar
class="toolbar"
[class.app-is-mobile]="mobileQuery.matches"
color="primary">
<button
mat-icon-button
(click)="lnav.toggle()"
*ngIf="mobileQuery.matches">
<mat-icon>menu</mat-icon>
</button>
{{title}}
<div class="fill-space"></div>
<span whoami></span>
</mat-toolbar>
<mat-drawer-container class="sidenav-container">
<mat-drawer
mode="side"
[opened]="!mobileQuery.matches">
<div class="content">
<mat-list>
<mat-list-item *ngFor="let route of nav">
<a mat-button routerLink="{{route.path}}" routerLinkActive="active" (click)="toggleMobileNav(lnav)">{{route.title}}</a>
</mat-list-item>
</mat-list>
</div>
</mat-drawer>
<mat-drawer-content>
<div class="content">
<router-outlet></router-outlet>
</div>
</mat-drawer-content>
</mat-drawer-container>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
import {
Component,
ChangeDetectorRef,
EventEmitter,
Output } from '@angular/core';
import { MediaMatcher } from '@angular/cdk/layout';
import { MatSidenav } from '@angular/material';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'Material PWA';
mobileQuery: MediaQueryList;
nav = [
{
'title': 'Home',
'path': '/'
},
{
'title': 'My Account (Part 2)',
'path': '/auth'
}
];
private _mobileQueryListener: () => void;
@Output() toggleSideNav = new EventEmitter();
constructor( changeDetectorRef: ChangeDetectorRef, media: MediaMatcher ) {
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
toggleMobileNav(nav: MatSidenav) {
if (this.mobileQuery.matches) {
nav.toggle();
}
}
}
import { NgModule } from '@angular/core';
import { CdkTableModule } from '@angular/cdk/table';
import { CdkTreeModule } from '@angular/cdk/tree';
import {
MatAutocompleteModule,
MatBadgeModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatStepperModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule,
} from '@angular/material';
@NgModule({
exports: [
CdkTableModule,
CdkTreeModule,
MatAutocompleteModule,
MatBadgeModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatStepperModule,
MatDatepickerModule,
MatDialogModule,
MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule,
]
})
export class MaterialModule { }
<form [formGroup]="signinForm">
<mat-form-field>
<input matInput placeholder="Email" type="email" formControlName="email" [errorStateMatcher]="errorStateMatcher" required>
<mat-hint *ngIf="!emailInput.value">Enter your email address</mat-hint>
<mat-error *ngIf="!emailInput.valid">
{{getEmailInputError()}}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Password" [type]="hide ? 'password' : 'text'" formControlName="password" [errorStateMatcher]="errorStateMatcher" required>
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
<mat-hint *ngIf="!passwordInput.value">Enter your password</mat-hint>
<mat-error *ngIf="!passwordInput.valid">
{{getPasswordInputError()}}
</mat-error>
</mat-form-field>
<button mat-raised-button color="primary">Sign In</button>
</form>
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss']
})
export class SignInComponent {
signinForm: FormGroup = new FormGroup({
email: new FormControl('',[ Validators.email, Validators.required ]),
password: new FormControl('', [ Validators.required ])
});
hide = true;
get emailInput() { return this.signinForm.get('email'); }
get passwordInput() { return this.signinForm.get('password'); }
constructor() { }
getEmailInputError() {
if (this.emailInput.hasError('email')) {
return 'Please enter a valid email address.';
}
if (this.emailInput.hasError('required')) {
return 'An Email is required.';
}
}
getPasswordInputError() {
if (this.passwordInput.hasError('required')) {
return 'A password is required.';
}
}
}
@import '~@angular/material/theming';
// Plus imports for other components in your app.
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();
// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$app-primary: mat-palette($mat-indigo, 800);
$app-accent: mat-palette($mat-pink, 800);
$app-active: mat-palette($mat-pink, 800);
// The warn palette is optional (defaults to red).
$app-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$app-theme: mat-light-theme($app-primary, $app-accent, $app-warn);
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($app-theme);
.active {
color: mat-color($app-primary);
}
.valid, .primary {
color: mat-color($app-primary);
}
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
form {
width: 100%;
}
form > * {
margin-bottom: 1.5em;
width: 100%;
}
a {
color: mat-color($app-accent);
}
.content {
padding: 0.5em;
}
.sidenav-content {
flex-direction: column;
}
.sidenav-container {
height: 90%;
}
.app-content {
flex: 1;
margin: 0 auto;
padding: 2em;
}
.cursor-pointer {
cursor: pointer;
}
.full-width {
width: 100%;
}
.active {
color: mat-color($app-active);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment