Angular:迭代ngForm控件?

时间:2017-08-16 17:10:10

标签: angular

目标是当用户单击按钮转到下一页时,如果页面已部分填写但无效,则阻止用户继续并显示错误指示符。

在模板驱动的表单中,我有几个容器元素使用NgModelGroup属性来表示"页面"在形式。在我的组件中,我想引用此集合,以便我可以使用索引访问它们。由于我无法得到这个集合(@ AJT_82评论为什么在下面),这是我的方法:

我上了一堂课来掌握有关页面的信息。

export class Page
{
    title: string;
    hasError: boolean;  //should the page display an error indicator
}

在我的组件中,我在ngOnInit

中填充数组pages: Page[]
ngOnInit()
{
    this.pages = [{title: "Page 1", hasError: false},
                  {title: "Page 2", hasError: false},
                  {title: "Page 3", hasError: false}]
}

和@DeborahK在她的回答中给了我

this.form.form.get('pg1')) 

让个人ngModelGroup命名为' pg'然后我可以在点击事件中使用+ currentPg + 1(+1以匹配View,因为数组从0开始),这将导致A)转到下一页或B)将hasError属性设置为是的,不会进入下一页。

let p = this.form.form.get("pg"+ (this.currentPg+1));
//if the page is partially filled out but not valid
if(p.invalid && p.dirty)
  this.pages[this.currentPg].hasError = true;
else
{
  //even if it's false, re-false it ;)
  this.pages[this.currentPg].hasError = false;

  //continue to next page. 
  //i.e. this.currentPg++ or this.currentPg--
}

回到模板中,要在选项卡或页面上显示错误指示器,我只需检查pages[currentPg].hasError属性。分配"有错误" tab元素的类,用于设置选项卡样式。

<div id="tabs">
  <a *ngFor="let p of pages" 
     [ngClass]="(p.hasError ? ' has-error' : '')"><p>{{p.title}}</p></a>
</div>

<form #f="ngForm">
  <div ngModelGroup="pg1"> <!-- pages[0] -->
    <div id="errorBlock" *ngIf="pages[currentPg].hasError">
      You had an error.
    </div>
    <div>
      <input ngModel/>
      <input ngModel/>
    </div>
    <div>
      <input ngModel/>
      <input ngModel/>
    </div>
  </div>
  <div ngModelGroup="pg2"> <!-- pages[1] -->
    <input ngModel/>
  </div>
</form>

以及这里的示例组件:

...
currentPg: number = 0;
pages: Page[] = [];
@ViewChild('f') public form: NgForm;

ngOnInit()
{
    this.pages = [{title: "Page 1", hasError: false},
                  {title: "Page 2", hasError: false},
                  {title: "Page 3", hasError: false}]
}

NextPage()
{
  let p = this.form.form.get("pg"+ (this.currentPg+1));
  //if the page is partially filled out but not valid
  if(p.invalid && p.dirty)
    this.pages[this.currentPg].hasError = true;
  else
  {
    //even if it's false, re-false it ;)
    this.pages[this.currentPg].hasError = false;

    //Do navigation logic. 
    //i.e. this.currentPg++ or this.currentPg--
  }
}

同样,如果能够获得ngModelGroups的集合并像使用数组一样使用它,很多事情就会消失。

2 个答案:

答案 0 :(得分:2)

此代码对我有用:

    Object.keys((<FormGroup>this.form.form.get('pg1')).controls).forEach(element => {
        console.log(element);
    });

但是关键问题(根据您的问题下面的评论)是此代码所在的。我将其添加为提交按钮流程的一部分。

在ngOnInit,ngAfterViewInit和ngAfterViewChecked中,这些元素的值为null / undefined。

如果您只需要知道表单组是否有效,您可以这样做:

    let isValid = this.form.form.get('pg1').valid;

或者,您可以使用选项卡式页面并在任何包含验证错误的页面上显示错误图标,如下所示:

enter image description here

在这个例子中,我使用的是模板驱动的表单。表单上的每个输入元素都如下所示:

        <div class="form-group" 
                [ngClass]="{'has-error': (productNameVar.touched || 
                                          productNameVar.dirty || product.id !== 0) && 
                                          !productNameVar.valid }">
            <label class="col-md-2 control-label" 
                    for="productNameId">Product Name</label>

            <div class="col-md-8">
                <input class="form-control" 
                        id="productNameId" 
                        type="text" 
                        placeholder="Name (required)"
                        required
                        minlength="3"
                        [(ngModel)] = product.productName
                        name="productName"
                        #productNameVar="ngModel" />
                <span class="help-block" *ngIf="(productNameVar.touched ||
                                                 productNameVar.dirty || product.id !== 0) &&
                                                 productNameVar.errors">
                    <span *ngIf="productNameVar.errors.required">
                        Product name is required.
                    </span>
                    <span *ngIf="productNameVar.errors.minlength">
                        Product name must be at least three characters.
                    </span>
                </span>
            </div>
        </div>

您可以在此处找到此示例的完整代码:https://github.com/DeborahK/Angular-Routing在APM-Final文件夹中。 (这是我的“Angular Routing”Pluralsight课程的代码。)

答案 1 :(得分:0)

foo( f: NgForm ){
    Object.values(f.controls).forEach( ctl => {
          console.log(ctl);
    } );
}