I have two components:
<app-google-login-button></app-social-login-button>
<app-facebook-login-button></app-facebook-login-button>
app-facebook-login-button looks like this:
<button type="button" class="btn btn-label btn-facebook" (click)="facebookSignIn()"
*ngIf="!(isMobile | async)?.matches">
<label>
<fa-icon [icon]="['fab', 'facebook']" size="xs"></fa-icon>
</label> Sign in with Facebook
</button>
<button type="button" class="btn btn-label btn-facebook" (click)="mobileFacebookSignIn()"
*ngIf="(isMobile | async)?.matches">
<label>
<fa-icon [icon]="['fab', 'facebook']" size="xs"></fa-icon>
</label> Sign in with Facebook
</button>
app-google-login-button looks like this:
<button type="button" class="btn btn-label btn-google" (click)="googleSignIn()" *ngIf="!(isMobile | async)?.matches">
<label>
<fa-icon [icon]="['fab', 'google']" size="xs"></fa-icon>
</label> Sign in with Google
</button>
<button type="button" class="btn btn-label btn-google" (click)="mobileGoogleSignIn()" *ngIf="(isMobile | async)?.matches">
<label>
<fa-icon [icon]="['fab', 'google']" size="xs"></fa-icon>
</label> Sign in with Google
</button>
I'd like to combine both and have a generic app-social-login-button. How would the component look like?
Define an interface that declares the configurable options, but also include a callback function for when the button is clicked. If you don't want to inject a callback for every button, then an alternative is to define a string token like "facebook" and pass that value to a shared service.
export interface SocialButton {
// button text
title: string;
// Font Awesome icon
icon: any;
// CSS class for the button
btn: string;
// make mobile just a condition of the click
click: (mobile: boolean) => void;
}
You can then pass an object of the above interface as a parameter to the component.
@Component({
selector: 'app-social-login-button',
template: `
<button type="button"
[ngClass]="getClass()"
(click)="click()">
<label>
<fa-icon [icon]="options.icon" size="xs"></fa-icon>
</label> Sign in with {{options.title}}
</button>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SocialLoginButtonComponent {
@Input()
public options: SocialButton;
public isMobile: Observable<any>;
public getClass() {
return {
'btn': true,
'btn-label': true,
[this.options.btn]: true
};
}
public click() {
this.isMobile
.pipe(first())
.subscribe(value => this.options.click(value));
}
}
You can define a shared service that will create the SocialButton options as an array.
@Injectable()
export class SocialButtonService {
public buttons(): SocialButton[] {
return [this.faceBook(), this.google()];
}
public faceBook(): SocialButton {
return {title: 'Facebook', icon: ['fab', 'facebook'], btn: 'btb-facebook', click: (m) => this.signIn('facebook', m)}
}
public google(): SocialButton {
return {title: 'Google', icon: ['fab', 'google'], btn: 'btb-google', click: (m) => this.signIn('google', m)}
}
public signIn(platform: string, mobile: boolean) {
// do work
}
}
You can show all the buttons easily now in another component.
@Component({
template: `
<app-social-login-button *ngFor="let option of options" [options]="option"></app-social-login-button>
`
})
export class SocialLoginButtonsComponent {
public options: SocialButton[];
public constructor(service: SocialButtonService) {
this.options = service.buttons();
}
}
From the HTML code provided, I can give you some suggestions.
Create an ENUM which would have list of social media. (this would restrict the value of social media which can be passed to the component)
Create a component for app-social-login-button with @Input params as Enum value (either Google or facebook).
Inside component SocialLoginButtonComponent, check for the passed value and have the HTML something like:
<button type="button" class="btn btn-label btn-facebook" (click)="SignIn()"
*ngIf="!(isMobile | async)?.matches">
<label>
<fa-icon [icon]="iconArray" size="xs"></fa-icon>
</label> Sign in with {{companyName}}
</button>
<button type="button" class="btn btn-label btn-facebook" (click)="SignInWithMobile()"
*ngIf="(isMobile | async)?.matches">
<label>
<fa-icon [icon]="iconArray" size="xs"></fa-icon>
</label> Sign in with {{companyName}}
</button>
in the component, check for the @Input param and set companyName, iconArray
.Configure SignIn() and SignInWithMobile() accordingly to call APIs of respective companies.
MediaService which will handle SignIn API calls depending on the Company Name. Try not to put all the logic in the component itself.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With