Как отобразить сводку сообщения об ошибке поверх формы в реактивных формах angular

У меня есть компонент сводки проверки, как показано ниже:

Компонент ниже извлекает ngform, но не может подписаться на statuschanges / Valuechanges и отобразить сводку сообщения об ошибке.

export class ValidationSummaryComponent implements OnInit {
  @Input() form: NgForm;
  errors: string[] = [];

 constructor() { }

ngOnInit() {
  if (this.form instanceof NgForm === false) {
  throw new Error('You must supply the validation summary with an NgForm.');
}
this.form.statusChanges.subscribe(status => {
  this.resetErrorMessages();
  this.generateErrorMessages(this.form.control);
});
}

 resetErrorMessages() {
this.errors.length = 0;
}

generateErrorMessages(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(controlName => {
  const control = formGroup.controls[controlName];
  console.info('control.......... ', control);
  const errors = control.errors;
  console.info('control.errors.......... ', control.errors);

  if (errors === null || errors.count === 0) {
    return;
  }
  // Handle the 'required' case
  if (errors.required) {
    this.errors.push(`${controlName} is required`);
  }
  // Handle 'minlength' case
  if (errors.minlength) {
    this.errors.push(`${controlName} minimum length is ${errors.minlength.requiredLength}.`);
  }
  // Handle custom messages.
  if (errors.message) {
    this.errors.push(`${controlName} ${errors.message}`);
  }
});

} }

и validation-summary.component.html

<div *ngIf = "errors?.length > 0" class = "validation-summary">
    <p>Please fix the following errors:</p>
<ul>
  <li *ngFor = "let error of errors">{{ error }}</li>
</ul>

dynamic-form.component.ts

constructor(public formBuilder: FormBuilder) {
}
productFormGroup: FormArray;

ngOnInit() {

this.productFormGroup = this.formBuilder.array([]);
  this.ProductList.forEach(product => {
      this.productFormGroup.push(this.formBuilder.group({
        productId: [product.productId],
        displayName: [product.displayName],
        productName: [product.productName, Validators.required]
      }));
    });

} }

dynamic-form.component.html, использующий сводку проверки.

    <div id = "mainWrapper">
      <app-validation-summary-component [form] = "userForm"></app-validation-summary-component> 
    <form #userForm = "ngForm">
<div [formGroup] = "product" *ngFor = "let product of 
         productFormGroup.controls>
      <label>{{product.get('displayName').value}}</label>
         <input  class = "form-control" 
       name = "product.get('displayName').value" 
        formControlName = "productName" required/>
 </div>
      <button class = "btn btn-primary" type = "submit" 
              [disabled] = "!productFormGroup.valid">Submit </button>
       <button class = "btn btn-primary" style = "margin-left: 30px" type = "reset" 
       (click) = "reset()"> Reset </button>
       </form>
</div>

Необходимо отображать сводку сообщений об ошибках поверх компонента динамической формы, отображающего список имен меток, который является пустым / недействительным.

вы можете использовать что-то вроде flash в узле, в зависимости от платформы, которую вы используете на стороне сервера.

jalil 18.12.2018 11:11

функция resetErrorMessages () должна быть {this.errors=[]}, вы не можете изменить "длину массива", вы должны изменить массив

Eliseo 23.04.2021 08:31
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
2
2 134
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

То, как вы зацикливаете элемент управления formarray formgroup, не является правильным внутри validation-summary.component. Созданный stackblitz объясняет решение.

https://stackblitz.com/edit/angular-mr49zh

Большое спасибо, Суреш! это именно то, что я хотел .... но при отображении сообщения об ошибке он выберет то же имя, что и «требуется отображаемое имя», вместо этого он должен выбрать уникальное значение и сказать, что требуется angular. Или React требуется, пожалуйста, обратитесь к руководству.

user1498069 18.12.2018 15:36

Вы должны использовать «отображаемое имя». так полезно для других.

Suresh Kumar Ariya 18.12.2018 15:46

Я проголосовал за, потому что у меня только 3 репутации :(, я действительно хочу отображать сообщения об ошибках, такие как angular, в настоящее время требуется отображение отображаемого имени для всех 3 полей, если в нем есть ошибки, вместо этого он должен исправить уникальное имя для каждого поля и говорят, что требуется angular или требуется реакция ....

user1498069 18.12.2018 15:52

я думаю, что нашел решение с приведенным ниже фрагментом кода .... if (formInnerControl && (_formControl.status === 'INVALID' || formInnerControl.errors) && formElement === 'displayName') {me.errors.push (formInnerControl.value + is required); } надеюсь, что это поможет другим ....

user1498069 18.12.2018 16:07

Вот группа функций, которая перебирает все элементы FromControl в FormGroup, включая вложенные элементы FormControl в FormArray и создание сводки проверки.

  getFormSummaryHtml(formGroup, fg_discription){
    let allErrors = this.getFormSummary(formGroup, '');
    let error_obj = this.setErrorFormat(allErrors, fg_discription)
    if (error_obj){
      let html = this.getHtmlFromObject(error_obj, '')   
  
      return html;
    }
  }

  getHtmlFromObject(error_obj, html) {
    if (error_obj.value) {
      for (let index = 0; index < error_obj.value.length; index++) {
        const element = error_obj.value[index];
        html += `<ul> <li>`;
        html += element.text;

        if (element.value) {
          html = this.getHtmlFromObject(element.value, html)
        }
        html += ` </li> </ul>`;
      }
    }
    else if (error_obj.length > 0) {
      html += `<ul>`;
      for (let index = 0; index < error_obj.length; index++) {
        const element = error_obj[index];
        html += element.text;
        if (element.value) {
          html = this.getHtmlFromObject(element.value, html)
        }
        else {
          // to Remove last appended text
          html = html.substring(0, html.length - element.text.length);
          html += `<li> ${element.text} </li>`
        }
      }
      html += `</ul>`;
    }
    else {
      html += error_obj.text;
    }
    return html
  }

  getFormSummary(formGroup, parentGroup) {
    let errors = []
    for (const key in formGroup) {
      if (Object.prototype.hasOwnProperty.call(formGroup, key)) {
        const element = formGroup[key];
        if (element instanceof FormGroup) {
          parentGroup = parentGroup == '' ? key : parentGroup + '>' + key;
          let terror = this.getFormSummary(element.controls, parentGroup)
          errors = [...errors, ...terror]
        }
        if (element instanceof FormArray) {
          parentGroup = parentGroup == '' ? key : parentGroup + '>' + key;
          for (let index = 0; index < element.controls.length; index++) {
            let ele = element.controls[index];
            let terror = this.getFormSummary(ele["controls"], parentGroup)
            errors = [...errors, ...terror]            
          }
        }
        if (element instanceof FormControl && element.valid == false && element.errors && Object.keys(element.errors).length > 0) {
          for (const errorTypes in element.errors) {
            errors.push(parentGroup + '>' + key + ':' + errorTypes)
          }
        }
      }
    }    
    return errors;
  }

  setErrorFormat(errors,discription){
    let errorObj: { text: string, key: string, value: Array<any>};

    for (let index = 0; index < errors.length; index++) {
      let element = errors[index];
      let elements = element.split(':');
      let error_elements = elements[0].split('>')
      error_elements.forEach((ele,idx) => {
        if (errorObj == null){
          errorObj = { text: discription[ele], key: ele, value: null };
        }
        else if (idx > 0){
          let error_t_obj = this.getErrorElement(errorObj, ele);

          let error_ele_obj = this.getErrorElement(errorObj, error_elements[idx - 1]);
          if (error_ele_obj && (error_t_obj == null || error_t_obj.key != error_elements[idx])) {
            let obj = { text: discription[ele], key: ele, value: null };
            error_ele_obj.value = error_ele_obj.value && error_ele_obj.value.length > 0 ? error_ele_obj.value : new Array();
            error_ele_obj.value.push(obj)
          }
        }        
      });      
    }
    return errorObj;
  }

  getErrorElement(error,s_key){
    if (error.key == s_key) {
      return error;
    }
    else if (error.value && error.value.length > 0) {
      for (let index = 0; index < error.value.length; index++) {
        let ele = error.value[index];
        let objerror = this.getErrorElement(ele, s_key);
        if (objerror != null ){
          return objerror;
        }
      }
    }
  }

Как это назвать?

getFormSummary(){
// This array contains FromControls name and Names of controls that user can understand
let fg_discription = {
  saleGroup: "Sales",
  sale_date: "Sale date",
  sale_type_id: "Sale type",
  deal_type_id: "Deal type",
  lender_id: "Lender",
  wholesaler_id: "Wholesaler",
  published_price: "Published price",
  pack: "Pack",
  allowance: "Allowance"
};
let html = this.getFormSummaryHtml(this.addSalesForm.controls, fg_discription)
return html;
}

validateFormOnSubmission() {
let form = this.addSalesForm.value;
let html = this.getFormSummary()
if (html == undefined) {
// Submit Form
    this.onSubmitAddSales();
}
else { // Show Html in POP message
  this.popMessage({ detail: "Following fields are  mandatory: ", data: { html }, key: "popup" })
}

}

попытайтесь отобразить ошибки "более угловым способом": не создавайте текст с .html, иначе используйте *ngFor непосредственно в .html

Eliseo 23.04.2021 08:29

Если вы хотите объект и отображать его с помощью ngFor, тогда let error_obj = this.setErrorFormat(allErrors, fg_discription) имеет объект ошибки.

Maaz Anzar 26.04.2021 19:42

Другие вопросы по теме