как создать динамическую форму из ответа API в angular 7?

#angular #angular7 #angular-reactive-forms #dynamic-forms #form-control

#угловатый #угловой 7 #угловые реактивные формы #динамические формы #управление формой

Вопрос:

Я работаю над динамической формой в angular 7. Я следовал пути, который упоминается на официальном сайте angular. Я успешно реализовал этот учебник, но мой сценарий отличается. какой тип ввода будет присутствовать в форме, и все его атрибуты будут получены из ответа API

это функция в сервисе, которая приносит мои данные. Пожалуйста, обратите внимание: на основе данных API я заполню свой массив вопросов, а пока я использовал фиктивные данные только для того, чтобы убедиться, что поток работает. вот как выглядит мой вопрос.service.ts выглядит так

 public response : QuestionBase<any>[] =[];      
getQuestions(id) {
  this.http.get(this.url 'selectAllFieldDetails/' id)
.pipe(map(
( response: Response) => {
    let data = response;
    console.log(data);


   let questions: QuestionBase<any>[] = [

      new DropdownQuestion({
        key: 'brave',
        label: 'Bravery Ratings',
        class:'form-control fis-form-control',
        formclass:'',
        options: [
          {key: 'solid',  value: 'Solid'},
          {key: 'great',  value: 'Great'},
          {key: 'good',   value: 'Good'},
          {key: 'unproven', value: 'Unproven'}
        ],
        required: true,
        order: 2
      }),

      new TextboxQuestion({
        key: 'process',
        label: 'Process name',
        value: 'IT ',
        class:'form-control fis-form-control',
        formclass:'',
        required: true,
        order: 1
      }),


    ];
    this.response =  questions.sort((a, b) => a.order - b.order);
   }
  ));
  console.log(this.response);
  return this.response;
}
 

Но проблема заключается в возврате функции перед ответом API, и она возвращает пустой массив. Именно так я звоню из create-ticket.component.ts

 ngOnInit() {
  this.questions = this.service.getQuestions(24);
  console.log(this.questions);
}
 

Каким-то образом я попытался сначала получить ответ API и сохранить его в некоторой переменной, а затем вызвать эту функцию this.service.getQuestions(24); но затем он показывает ошибку, которая

 Error: Cannot find control with name: 'process'
at _throwError (forms.js:1775)
at setUpControl (forms.js:1683)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addControl (forms.js:4532)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName._setUpControl (forms.js:5030)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:4980)
at checkAndUpdateDirectiveInline (core.js:9239)
at checkAndUpdateNodeInline (core.js:10507)
at checkAndUpdateNode (core.js:10469)
at debugCheckAndUpdateNode (core.js:11102)
at debugCheckDirectivesFn (core.js:11062)
 

и данные Formgorup остаются пустыми.
Пожалуйста, помогите мне в этой проблеме.
Заранее спасибо

Комментарии:

1. пожалуйста, предоставьте весь код или, что еще лучше, stackblitz для минимального устранения неполадок.

2. и проблема в том, что вы не подписываетесь на запрос get, чтобы выполнить запрос.

Ответ №1:

Итак, наконец, после долгих исследований и разработок я это сделал. в основном было две проблемы

  1. функция в сервисе отвечает перед ответом API
  2. форма создается до того, как данные поступают в бизнес

Итак, для первого выпуска я использовал концепцию async await функции в angular

В create-ticket.component.ts мы добавили асинхронность и ожидание, подобные этому.

 async ngOnInit() {
    this.questions = await this.service.getQuestionss(24);
    if(this.questions.length>0){
       this.showForm=true;
    }
}
 

и в сервисе мы возвращаем обещание

 async getQuestionss(id): Promise<any> {
     this.responses = await this.apiServce.getAllInputFields(id).toPromise();
}
 

он отвечает как обещание, поэтому он ожидает ответа api. this.apiservice.getAllInputFields(id) это просто вызов http api с сервера.

Для 2-й проблемы я использовал только небольшое решение. я добавил *ngIf в форму, поэтому, когда api отвечает данными, тогда только форма начинает строиться.

 <app-dynamic-forms *ngIf="showForm" [questions]="questions"></app-dynamic-forms>
 

Вот и все, и проблема решена.

Ответ №2:

устаревшая информация, основанная на stackblitz

Вы должны всегда подписываться на асинхронный вызов, чтобы он выполнялся

 ngOnInit() {
  this.questions = this.service.getQuestions(24).subscribe(result => {
                do something with result }, 
      err => { something went wrong });
}
 

Вот stackblitz, основанный на вашем :
https://stackblitz.com/edit/angular-h8zakj?embed=1amp;file=src/app/question .сервис.ts

как я уже сказал, возникла проблема с вашим setTimeout. данные были недоступны там, где вы этого хотели.

Комментарии:

1. свойство subscribe не существует для типа QuestionBase<any>[]. это мой интерфейс questionbase. экспортировать класс QuestionBase<T> { значение: T; ключ: строка; метка: строка; требуется: логическое значение; порядок: число; класс: строка; ControlType: строка; formclass: строка; конструктор(параметры: { значение?: T, ключ?: строка, метка?: строка, обязательно?: логическое значение, порядок?: номер, класс?: строка, формкласс?: строка, тип элемента управления?: строка } = {}) { } }

2. да, он должен вернуть вызов thiis.http.get как наблюдаемый из своего сервиса и изменить возвращаемый тип. в любом случае, он смешал много неполного материала. вот почему я запросил код режима

3. вы можете увидеть здесь angular.io/generated/live-examples/dynamic-form/stackblitz.html

4. в конце он должен вернуться getQuestions(id) { this.http.get(this.url 'selectAllFieldDetails/' id) .pipe(map( ... как наблюдаемый. на данный момент ему нужно повторно использовать наблюдаемую часть своих фиктивных данных, чтобы заставить это работать

5. stackblitz.com/edit/angular-ytkydp это URL-адрес редактора. вы можете видеть проблему, с которой я столкнулся. Я вызвал функцию settimeout вместо http-вызова, потому что поведение такое же. если вы удалите функцию settimeout, появится форма.