2017-02-19 33 views
2

Чем больше я продвигаюсь с моим сайтом в Angular 2, тем больше кажется, что Elvis Operator - это магическая сила, которая делает все возможное. Каждый шаг, который я предпринял, включал в себя выяснение того, как правильно применить его к каждому экземпляру всего, что сделано с данными. Я чувствую, что если бы «нормальный» нуждался в ? практически на всех ваших действиях в реальной жизни с фактическими данными, о которых упоминалось бы в Angular docs.Как я могу избежать использования Elvis Operator?

Чтобы привести пример, я только недавно научился настраивать FormGroups для реактивных форм. Следуя вместе с шагами по 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: []); 
} 

Это не имеет значения, правильно ли я привязка к HTML, привязка к атрибуту, проходя через @Input и @Output, или делать что-то в функции; Elvis Operator - это тролль на мосту с сумасшедшей загадкой, которая занимает неделю, чтобы понять, что делать, что я уже ТЫ ЧТО Я узнал. Сначала я подумал, что это просто небольшая причуда, с которой им приходилось работать, но теперь для меня это слишком большая вещь, потому что это просто ошибка на их конце, иначе я думаю, что будет более обширная информация об этом, потому что это означало бы, что NOBODY сможет использовать 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> 

Grandchild Компонент

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

    } 
} 

Grandchild Шаблон

<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, потому что я использую бутстрап, который загромождает треску ING.

На данный момент @Output, отправляющий выбранное значение до родительского, дает результаты только в некоторой тестовой привязке, которую я сделал с трубой | json на всем объекте, но регистрируется как неопределенный, поэтому, если вы чувствуете, что что-то не так с тем, как я Я это делаю, я уже знаю, что он работает неправильно.

Причина, по которой я делаю это таким образом, кроме того, что это единственный способ получить то, что нужно сделать defined, потому что GrandChild Component будет использоваться в других местах сайта для других вопросов. Иногда я просто использую id для запуска логики, иногда я буду тянуть ответ в экземпляр пользовательских данных, которые будут сохранены в базе данных. Поэтому мне не было смысла просто отправлять всю модель обратно в цепочку только для того, чтобы извлечь пару значений, плюс, если само значение может быть данными, которые устраняют головную боль от таргетинга вложенных значений, учитывая, как я не могу потяните мои данные без использования Elvis Operator.

Я натолкнулся на тонны уловок. Я пытался использовать только для них, чтобы они не работали, потому что всегда приходило в голову undefined, пытаясь узнать, как заставить его работать, что было слишком сложно, потому что я не знал если я делал что-то неправильно с точки зрения его работы или если я делал что-то неправильно в отношении применения Elvis Operator к нему. Я удалил здесь немало вопросов из-за downvotes и просьбы закрыть их, потому что с точки зрения тех из вас, кто является мастерами с Angular, это был ужасный вопрос или ужасный способ спросить об этом. Так что, надеюсь, кто-то может помочь пролить свет на то, что мне нужно делать с моими данными, чтобы иметь возможность просто делать то, что предлагает Angular.io, без лишних неожиданных исправлений и обходных решений просто потому, что я вызываю фактическую базу данных, а не издевку -данные, определенные локально.

ответ

1

Вы используете реактивные формы, а это значит, что в любом случае у вас будет тонна [в основном бесполезного] кода.

Просто используйте формы с шаблонами, если у вас нет конкретной необходимости в реактивных формах.

0

Вы можете обернуть большие площади с помощью *ngIf, чтобы даже не добраться до той точки, где требуется ?..

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

может быть

<ng-container *ngIf="busExpInformation"> 
    <h1>{{busExpInformation.title}}</h1> 
    <p>{{busExpInformation.intro}}</p> 
</ng-container> 

Если вы обернуть весь шаблон компонентов с таким ng-container и перечислить все ASync загруженные поля с busExpInformation && a && b && c, то, возможно, никогда бы потребность в ?.

You может также использовать преобразователь для предотвращения добавления компонента до того, как данные будут доступны (https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard)