angular - 如何避免需要使用 Elvis Operator?

标签 angular typescript firebase firebase-realtime-database angularfire

我在 Angular 2 中的网站进展得越多,Elvis Operator 似乎就越多。是使这一切成为可能的神奇力量。我采取的每一步都涉及弄清楚如何将它正确地应用于对数据完成的所有事情的每个实例。我觉得需要一个 ? 是否“正常”关于你在现实生活中使用实际数据所做的几乎所有事情,Angular 文档都会提到它。

举个例子,我最近才学会如何设置FormGroups对于 react 形式。按照 Angular.io 上的步骤,我的表单组看起来像这样。

createForm() {
    this.quesForm = this.fbuild.group({
        question: this.featureQuestion.question,
        id      : this.featureQuestion.id,
        name    : this.featureQuestion.name,
        answers : this.fbuild.array([])
    });
    this.setAnswers(this.featureQuestion.answers);
}

get answers(): FormArray {
    return this.quesForm.get('answers') as FormArray;
};

mock-data 一起工作我在 const 中创建它工作得很好。然而,当我想用​​“真实数据”“真实世界使用”它时,我不得不再花 3 到 4 天的时间发现我需要这样做。
createForm() {
    this.quesForm = this.fbuild.group({
        question: this.featureQuestion ? this.featureQuestion.question: '',
        id      : this.featureQuestion ? this.featureQuestion.id: '',
        name    : this.featureQuestion ? this.featureQuestion.name: '',
        answers : this.fbuild.array([])
    });
    this.setAnswers(this.featureQuestion ? this.featureQuestion.answers: []);
}

我是否绑定(bind)到 html、绑定(bind)到一个属性、通过 @Input 都没有关系和 @Output ,或在函数中做某事; Elvis Operator是桥上的巨魔带着一个疯狂的谜语需要一周的时间才能弄清楚只是为了做我已经认为我学到的东西。起初我认为这只是他们必须解决的一个小怪癖,但现在这对我个人来说太大了,不能成为他们最终的一个错误,否则我认为会有更广泛的信息,因为这意味着没有人能够在现实生活中使用 Angular,而无需每一步都应用它。这意味着它必须是我正在做的事情。

这是我目前如何从 Firebase 调用我的数据的示例。

服务
export class HomeService {
    BusImage : FirebaseObjectObservable<any>;

    constructor(private af: AngularFire) {}

    getBusImage() {
        this.BusImage = this.af.database.object('/page_area_business_image')
        as FirebaseObjectObservable<any>

        return this.BusImage;
    }
}

父组件
export class ExpBusinessComponent implements OnInit {

    private busImageO       : FirebaseObjectObservable<any>;
    private busImageQues01O : FirebaseObjectObservable<any>;
    private busImageQues02O : FirebaseObjectObservable<any>;

    constructor(private _homeService: HomeService) {}

    ngOnInit() {
        this._homeService.getBusImage().subscribe(BusImage => {
            this.busImageO       = BusImage.expand;
            this.busImageQues01O = BusImage.questions.question01;
            this.busImageQues02O = BusImage.questions.question02;
        });
    }
}

父模板
<h1>{{busExpInformation?.title}}</h1>
<p>{{busExpInformation?.intro}}</p>

<business-image
    [busImageI]        =  "busImageO"
    [busImageQues01I]  =  "busImageQues01O"
    [busImageQues02I]  =  "busImageQues02O">
</business-image>

子组件
export class BusinessImageComponent implements OnChanges, OnInit {
    @Input('busImageI')         busImage    : FirebaseObjectObservable<any>;
    @Input('busImageQues01I')   question01  : FirebaseObjectObservable<any>;
    @Input('busImageQues02I')   question02  : FirebaseObjectObservable<any>;

    public selectedI(selected){ this.selectedAnswer = selected };

    selectedAnswer: any;

    expbTrigger         : boolean = false;
    expb2Trigger        : boolean = false;
}

子模板
<multiple-choice-radio *ngIf="expbTrigger"
    [question]  = "question01"
    (selectedO) = "selectedI($event)"
></multiple-choice-radio>

孙组件
export class MultipleChoiceRadioComponent implements OnInit, OnChanges {
    @Input('question') featureQuestion: QuestionModel;
    @Output() selectedO: EventEmitter<any> = new EventEmitter();

    selected = {value1: '', value2: ''};

    quesForm: FormGroup;

    public sendAnswer = (): void => {
         this.selectedO.emit(this.selected);
     }

    constructor(private fbuild : FormBuilder) {}

    ngOnChanges() {
        this.createForm();
    }

    createForm() {
        this.quesForm = this.fbuild.group({
            question: this.featureQuestion ? this.featureQuestion.question: '',
            id      : this.featureQuestion ? this.featureQuestion.id: '',
            name    : this.featureQuestion ? this.featureQuestion.name:  '',
            answers : this.fbuild.array([])
        });
        this.setAnswers(this.featureQuestion ? this.featureQuestion.answers: []);
    }

    get answers(): FormArray {
        return this.quesForm.get('answers') as FormArray;
    };

    setAnswers(answers : Answers[]){
        const answersFGs        = answers.map(answers => this.fbuild.group(answers));
        const answersFormArray  = this.fbuild.array(answersFGs);

        this.quesForm.setControl('answers', answersFormArray);
    }

    getSelected(ans) {
        this.selected = { value1: ans.id, value2: ans.answer };

    }
}

孙子模板
<form [formGroup]="quesForm" novalidate>
    <fieldset [attr.id]="quesForm.value.id">

        <label>
            {{quesForm.value.question}}
        </label>

        <div>

            <div *ngFor="let ans of quesForm.value.answers">
                <div>

                    <input type="radio"
                        [attr.name]  = "quesForm.value.name"
                        [attr.id]    = "ans.id"
                        [attr.value] = "ans.answer"
                        (click)      = "getSelected(ans)"
                        (click)      = "sendAnswer()"
                        hidden
                    />

                    <label [attr.for]="ans.id">
                        {{ans.answer}}
                    </label>
                </div>
            </div>

        </div>

    </fieldset>
</form>

我刚刚提供的大部分代码都被省略了,以消除基本相同的过程,只是将不同的数据发送到不同的地方,我还从 HTML 中消除了类,因为我使用了使编码困惑的 Bootstrap 。

截至目前 @Output将选定的值发送给父级只会在我用 | json 做的一些测试绑定(bind)中给出结果整个对象上的管道,但记录为未定义所以如果你觉得我的做法有问题,我已经知道它不能正常工作。

我以这种方式做事的原因除了它是我让事情变得更好的唯一方法 defined是因为GrandChild Component将在网站的其他地方用于其他问题。有时我只会使用 id为了触发逻辑,有时我会将答案提取到将保存到数据库的用户数据实例中。所以对我来说,仅仅将整个模型发送回链只是为了提取几个值是没有意义的,而且如果值本身可以是消除定位嵌套值的头痛的数据,考虑到我怎么不能在没有 Elvis Operator 的情况下提取我的数据在某处正确应用。

我遇到了大量的 Angular 技巧,我试图使用它们只是为了让它们不起作用,因为它总是出现 undefined在尝试学习如何使其工作时,这非常困难,因为我不知道我是否在使其工作方面做错了什么,或者我是否在应用 Elvis Operator 方面做错了什么。到它。由于反对票和关闭它们的请求,我在这里删除了很多问题,因为从你们这些 Angular 大师的 Angular 来看,这是一个可怕的问题,或者是可怕的提问方式。所以希望有人可以帮助阐明我需要对我的数据做什么,以便能够按照 Angular.io 建议的方式做事,而无需所有额外的意外修复和解决方法,因为我正在调用一个实际的数据库而不是模拟- 本地定义的数据。

最佳答案

您正在使用响应式(Reactive)形式,这意味着无论如何您最终都会有大量 [大部分是无用的] 代码。

除非您对响应式表单有特定需求,否则只需使用模板驱动的表单。

关于angular - 如何避免需要使用 Elvis Operator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42333943/

相关文章:

angular - Angular DOM 中的 StaticInjectorError

ios - 如何按时间顺序对 Firebase 数据库进行排序?

node.js - Firebase Firestore 模拟器如何工作?

javascript - 为什么要在Component中写Object=Object才能在Angular中获取Object.keys?

angular - 如何在@ ngrx/store的createAction中将数组用作参数

arrays - Angular 2 - 从嵌套数组创建 CSV 文件

javascript - 如何使用 mat-select 与 react 形式 formarray Angular

firebase - Firebase:激活只读和非实时模式以提高浏览器性能

dictionary - 未调用 http 响应上的 RxJs/Angular2 映射函数

typescript - Angular 2 - 直接从 Observable 返回数据