Skip to content

Instantly share code, notes, and snippets.

@kinggolf
Created February 28, 2017 19:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kinggolf/e48c6c8f72d570922bf3606b14bf08b4 to your computer and use it in GitHub Desktop.
Save kinggolf/e48c6c8f72d570922bf3606b14bf08b4 to your computer and use it in GitHub Desktop.
Login component with Angular Reactive Forms
<GridLayout>
<GridLayout #background scaleX="1.4" scaleY="1.4" class="background"
(loaded)="startBackgroundAnimation(background)">
</GridLayout>
<StackLayout #mainContainer class="main-container">
<Label class="main-label" text="Cobbl in your life" [color]="isLoggingIn? 'white' : 'white'"></Label>
<GridLayout #formControls class="form-controls" rows="auto, auto, auto" translateY="50" [formGroup]="loginSignupForm">
<TextField #email hint="Email Address" keyboardType="email" returnKeyType="next"
(returnPress)="focusPassword()" formControlName="email" [isEnabled]="!isAuthenticating"
autocorrect="false" autocapitalizationType="none" row="0">
</TextField>
<TextField #password hint="Password" secure="true" returnKeyType="isLoggingIn ? 'done' : 'next'"
(returnPress)="submitOrFocusUsername()" formControlName="password" [isEnabled]="!isAuthenticating" row="1">
</TextField>
<TextField #name hint="User Name" returnKeyType="done" [opacity]="isLoggingIn ? 0 : 1"
(returnPress)="submit()" formControlName="username" [isEnabled]="!isAuthenticating" row="2">
</TextField>
<ActivityIndicator [busy]="isAuthenticating" [visibility]="isAuthenticating ? 'visible' : 'collapse'"
row="2" style="color:#ffffff;">
</ActivityIndicator>
</GridLayout>
<Button [text]="isLoggingIn ? 'Login' : 'Sign up'" [isEnabled]="!isAuthenticating" class="submit-button"
(tap)="submit()"[isEnabled]="loginSignupForm.valid" [opacity]="loginSignupForm.valid ? '1' : '0.5'">
</Button>
<Label class="forgot-password-label" text="Forgot password?"
(tap)="forgotPassword()" [opacity]="isLoggingIn ? 1 : 0">
</Label>
<Label text="- or -" class="or"></Label>
<StackLayout #signUpStack class="sign-up-stack" (tap)="changeLoginSignup()" translateY="50">
<Label [text]="isLoggingIn ? 'Sign up here' : 'Back to login'"></Label>
</StackLayout>
</StackLayout>
<!-- logo that appears within the container -->
<AbsoluteLayout #logoContainer class="logo-container">
<Image src="res://logo_login" stretch="none"></Image>
</AbsoluteLayout>
</GridLayout>
import { Component, ElementRef, OnInit, ViewChild } from "@angular/core";
import { Router, NavigationExtras } from "@angular/router";
import { Color } from "color";
import { connectionType, getConnectionType } from "connectivity";
import { Animation } from "ui/animation";
import { View } from "ui/core/view";
import { prompt } from "ui/dialogs";
import { TextField } from "ui/text-field";
import { Page } from "ui/page";
import { alert, setHintColor, LoginService, User, logEventToAnalytics, logViewToAnalytics } from "../shared";
import { RouterExtensions } from 'nativescript-angular/router/router-extensions';
import { BackendService } from "../shared/backend.service";
import { ensureValidToken, ITnsOAuthOptionsFacebook, initFacebook } from "nativescript-oauth";
import { Validators, FormBuilder, FormControl, FormGroup, AbstractControl } from '@angular/forms';
import { validate } from "email-validator";
@Component({
selector: "cbl-login",
templateUrl: "login/login.component.html",
styleUrls: ["login/login-common.css", "login/login.component.css"],
})
export class LoginComponent implements OnInit {
user: User;
isLoggingIn: boolean;
isAuthenticating: boolean;
loginSignupForm: FormGroup;
userEmailControl: AbstractControl;
userPasswordControl: AbstractControl;
userNameControl: AbstractControl;
@ViewChild("mainContainer") mainContainer: ElementRef;
@ViewChild("logoContainer") logoContainer: ElementRef;
@ViewChild("formControls") formControls: ElementRef;
@ViewChild("signUpStack") signUpStack: ElementRef;
@ViewChild("email") email: ElementRef;
@ViewChild("password") password: ElementRef;
@ViewChild("name") name: ElementRef;
constructor(private router: Router, private page: Page, private fb: FormBuilder,
private userService: LoginService, private routerExtensions: RouterExtensions) {
this.loginSignupForm = this.fb.group({
email: ['', [Validators.required, Validators.maxLength(60), Validators.pattern('[A-Za-z,. :0-9/()-_@]*')]],
password: ['', [Validators.required, Validators.minLength(5), Validators.maxLength(20), Validators.pattern('[A-Za-z,. :0-9/()-_?!]*')]],
username: ['', [Validators.minLength(5), Validators.maxLength(40), Validators.pattern('[A-Za-z,. :0-9/()-_?!]*')]],
});
this.userEmailControl = this.loginSignupForm.controls['email'];
this.userPasswordControl = this.loginSignupForm.controls['password'];
this.userNameControl = this.loginSignupForm.controls['username'];
}
ngOnInit() {
this.page.backgroundSpanUnderStatusBar = true;
this.page.actionBarHidden = true;
this.isLoggingIn = true;
this.isAuthenticating = false;
this.setTextFieldColors();
this.showMainContent();
}
focusPassword() {
this.password.nativeElement.focus();
}
submit() {
if (!validate(this.userEmailControl.value)) {
alert("Enter a valid email address.");
return;
}
this.isAuthenticating = true;
if (this.isLoggingIn) {
this.login();
} else {
this.signUp();
}
}
submitOrFocusUsername() {
if (this.isLoggingIn) {
this.login();
} else {
this.signUp();
}
}
login() {
/*
if (getConnectionType() === connectionType.none) {
alert("Internet connection required to log in.");
return;
} */
logEventToAnalytics("Account", "Login");
let user = {
email: this.userEmailControl.value,
password: this.userPasswordControl.value
};
console.log("In login, user = " + user);
this.userService.login(user)
.subscribe(v => {
this.isAuthenticating = false;
// this.router.navigate(["/board"]);
// Code below was used in order to remove back button upon login!
// this.routerExtensions.canGoBack();
BackendService.token = v.data.access_token;
this.routerExtensions.navigate(["/board"], {
queryParams: { newUser: "old_user" },
clearHistory: true
});
},
(error) => {
alert("Unfortunately we could not find your account.");
this.isAuthenticating = false;
});
}
signUp() {
if (getConnectionType() === connectionType.none) {
alert("Internet connection required to register.");
return;
}
let user = {
email: this.userEmailControl.value,
password: this.userPasswordControl.value,
name: this.userNameControl.value
};
this.userService.register(user)
.subscribe(v => {
// alert("Your account was successfully created.");
this.isAuthenticating = false;
BackendService.token = v.data.access_token;
this.routerExtensions.navigate(["/board"], {
queryParams: { newUser: "new_user" },
clearHistory: true
});
},
(message) => {
// TODO: Verify this works
if (message.match(/same user/)) {
alert("This email address is already in use.");
}
else {
alert("Unfortunately we were unable to create your account.");
}
this.isAuthenticating = false;
});
}
forgotPassword() {
prompt({
title: "Forgot Password",
message: "Enter the email address you used to register for Cobbl to reset your password.",
defaultText: "",
okButtonText: "Ok",
cancelButtonText: "Cancel"
}).then((data) => {
if (data.result) {
this.userService.resetPassword(data.text.trim())
.subscribe(() => {
alert("Your password was successfully reset. Please check your email for instructions on choosing a new password.");
}, () => {
alert("Unfortunately, an error occurred resetting your password.");
});
}
});
}
changeLoginSignup() {
this.isLoggingIn = !this.isLoggingIn;
console.log("In changeLoginSignup, this.isLoggingIn = " + this.isLoggingIn);
this.setTextFieldColors();
let mainContainer = <View>this.mainContainer.nativeElement;
mainContainer.animate({
backgroundColor: this.isLoggingIn ? new Color("rgba(0, 0, 0, 0.7)") : new Color("rgba(0, 0, 0, 0.9)"),
duration: 200
});
}
startBackgroundAnimation(background) {
background.animate({
scale: { x: 1.2, y: 1.2 },
duration: 2000
});
}
showMainContent() {
let mainContainer = <View>this.mainContainer.nativeElement;
let logoContainer = <View>this.logoContainer.nativeElement;
let formControls = <View>this.formControls.nativeElement;
let signUpStack = <View>this.signUpStack.nativeElement;
let animations = [];
mainContainer.style.visibility = "visible";
logoContainer.style.visibility = "visible";
// Fade in the main container and logo over one half second.
animations.push({ target: mainContainer, opacity: 1, duration: 500 });
animations.push({ target: logoContainer, opacity: 1, duration: 500 });
// Slide up the form controls and sign up container.
animations.push({ target: signUpStack, translate: { x: 0, y: 0 }, opacity: 1, delay: 500, duration: 150 });
animations.push({ target: formControls, translate: { x: 0, y: 0 }, opacity: 1, delay: 650, duration: 150 });
// Kick off the animation queue
new Animation(animations, false).play();
}
setTextFieldColors() {
let emailTextField = <TextField>this.email.nativeElement;
let passwordTextField = <TextField>this.password.nativeElement;
let nameTextField = <TextField>this.name.nativeElement;
emailTextField.color = new Color("white");
passwordTextField.color = new Color("white");
nameTextField.color = new Color("white");
let hintColor = new Color("white");
setHintColor({ view: emailTextField, color: hintColor });
setHintColor({ view: passwordTextField, color: hintColor });
setHintColor({ view: nameTextField, color: hintColor });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment