角度中的组件组成/卷曲/预绑定

时间:2018-03-16 12:11:24

标签: angular

我在Angular中遇到以下问题,我无法摆脱困境。 让我们假设有一个Angular Wizard组件。该向导组件具有约10个输入/输出参数,如initialSteponSubmitonStepChangecurrentStepisLoading等。 现在,我需要使用向导创建3个页面。第1页有步骤1,第2页有步骤2,第3页有步骤1& 2& 3.它在标记中的样子:

Wizard1:

<wizard *ngIf="process" initialStep="0" (onSubmit)="onSubmit()" (onStepChange)="onStepChange($event)" [loading]="loading" infoPaletteText="You cannot submit" title="title1">
    <wizard-step caption="steptitle1">
        <step1-content></step1-content>
    </wizard-step>
</wizard>

向导2:

<wizard *ngIf="process" initialStep="0" (onSubmit)="onSubmit()" (onStepChange)="onStepChange($event)" [loading]="loading" infoPaletteText="You cannot submit" title="title2">
    <wizard-step caption="steptitle2">
        <step2-content></step2-content>
    </wizard-step>
</wizard>

Wizard3:

<wizard *ngIf="process" initialStep="0" (onSubmit)="onSubmit()" (onStepChange)="onStepChange($event)" [loading]="loading" infoPaletteText="You cannot submit" title="title3">
    <wizard-step caption="steptitle1">
        <step1-content></step1-content>
    </wizard-step>
    <wizard-step caption="steptitle2">
        <step2-content></step2-content>
    </wizard-step>
    <wizard-step caption="steptitle3">
        <summary></summary>
    </wizard-step>
</wizard>

如您所见,向导组件定义对于所有组件绝对相同。标题是唯一的易变参数。我需要某种currying或组合,我得到带有1个参数的新向导组件,其余的都是固定的。

Angular不鼓励继承组件,也不继承模板。因此,无论组件是什么,我都希望将向导的onSubmit方法绑定到onSubmit方法,loading绑定到loading变量等。

如何以正确和聪明的方式解决这个问题?

修改

受到this article的启发,我决定尝试这种疯狂的方式:

为静态类型检查创建界面:

export interface ISurveyAttachable {
    onSubmit(): void;
    onStepChange(event): void;
    loading: boolean;
}

创建指令,该指令只能附加到向导组件

@Directive({
    selector: 'wizard[survey]'
})
export class SurveyWizardDirective implements DoCheck, OnDestroy {

    private subs = [];

    @Input('survey')
    set param(value: ISurveyAttachable) {
        this.attachableComponent = value;
        this.unsibscribe();

        if (!value) return;
        this.subs.push(this.wizardForm.onStepChange.subscribe(value.onStepChange.bind(value)));
        this.subs.push(this.wizardForm.onSubmit.subscribe(value.onSubmit.bind(value)));
    }

    get param() : ISurveyAttachable{
        return this.attachableComponent;
    }

    private attachableComponent: ISurveyAttachable;

    constructor(private wizardForm: WizardComponent) { }

    ngDoCheck(): void {
        if (!this.attachableComponent) {
            return;
        }
        this.wizardForm.loading = this.attachableComponent.loading;
    }

    private unsibscribe() {
        this.subs.forEach((sub) => sub.unsubscribe());
        this.subs = [];
    }

    ngOnDestroy(): void {
        this.unsibscribe();
    }
}

然后,我可以在目标组件中以这种方式使用指令:

<wizard *ngIf="process" [survey]="this">
<!--steps here-->
</wizard>

因此,它表明我的想法是可行的,但它有许多缺点:

  1. 还不清楚如何消除* ngIf(扩展ngIf指令?可能从ngIf借用一些代码?)
  2. 传递this变量看起来很难看。可以在@Component声明中附加指令。但在这种情况下,我忽略了WizardComponent
  3. 的引用
  4. 手动数据绑定......但它看起来像是一个很好的权衡。
  5. 我认为上面的解决方案更像是Angular高级主题中的练习而不是生产就绪代码。然而,这个需要在3个地方更新相同代码的地方过去已经造成了一些错误。

    感谢任何新想法。

1 个答案:

答案 0 :(得分:-1)

您被迫将事件发射器绑定到父级。

否则,您必须使用服务。我们假设它被称为WizardService

然后在你的代码中,而不是写

this.onSubmit.emit(value);

你会写

this.service.submit(value);

你的HTML代码会减少。如果只有标题发生变化,那么你只有这个

<wizard title="title1">
    <!-- your content -->
</wizard>