进一步推广按钮组件

时间:2019-07-06 05:58:19

标签: angular

我有两个组成部分:

  <app-google-login-button></app-social-login-button>
  <app-facebook-login-button></app-facebook-login-button>

app-facebook-login-button看起来像这样:

<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看起来像这样:

<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>

我想将两者结合起来并使用通用的app-social-login-button。该组件的外观如何?

2 个答案:

答案 0 :(得分:2)

通过提供的HTML代码,我可以给您一些建议。

  1. 创建一个包含社交媒体列表的ENUM。 (这将限制可以传递给组件的社交媒体的价值

  2. 使用app-social-login-button参数作为Enum值为@Input创建一个组件(Google或Facebook)。

  3. 在组件SocialLoginButtonComponent中,检查传递的值,并使HTML类似:

<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>

组件中,检查@Input参数并设置companyNameiconArray 相应地配置SignIn()SignInWithMobile()以调用相应公司的API。

  1. 您还可以创建一个MediaService来处理SignIn的API调用,具体取决于Company Name。尽量不要将所有逻辑放在组件本身中。

答案 1 :(得分:2)

定义一个接口,该接口声明可配置的选项,但还包括单击按钮时的回调函数。如果您不想为每个按钮注入回调,那么另一种方法是定义一个字符串令牌,例如“ facebook”,并将该值传递给共享服务。

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;
}

然后可以将上述接口的对象作为参数传递给组件。

@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));
    }
}

您可以定义一个共享服务,该服务将创建SocialButton选项作为数组。

@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
    }
}

您现在可以轻松地在另一个组件中显示所有按钮。

@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();
    }
}