title: How to set attribute to FormControl programmatically?
body: <p><strong>Big question short:</strong> Basically what I want to achieve is, to apply <code>readonly</code> attribute to <code>FormControl</code> (textbox), right when it's created programmatically.</p>
  
  <p><strong>Full scenario:</strong>
  I have a <code>Form</code> that has a <code>FormRow</code> whose elements (<code>FormGroup</code>s) are partly generated dynamically. I also have given an option to append a row on click of a button.</p>
  
  <p>I want the <code>FormGroup</code>'s <code>FormControl</code>s (textboxes) that are generated dynamically to be <code>readonly</code>, but the manually added <code>FormControl</code>s should be editable.</p>
  
  <p>How can I achieve this?</p>
  
  <pre><code>&lt;div formArrayName="rows"&gt;
      &lt;div class="row" *ngFor="let row of detailForm.get('rows').controls; let i = index" [formGroupName]="i"&gt;
          &lt;div class="col-xs-1 text-center"&gt;
              &lt;input type="checkbox" [(ngModel)]="detailSelected[i]" [ngModelOptions]="{standalone: true}"&gt;
          &lt;/div&gt;
          &lt;div class="col-xs-2"&gt;
              &lt;input type="text" class="form-control" formControlName="account" (change)="getAccountAssociatedDetails(detailForm.get(['rows', i, 'account']), 'account', i)"&gt;
          &lt;/div&gt;
          &lt;div class="col-xs-2"&gt;
              &lt;input type="text" class="form-control" formControlName="detailNo" (change)="getAccountAssociatedDetails(detailForm.get(['rows', i, 'detailNo']), 'detail', i)"&gt;
          &lt;/div&gt;
          &lt;div class="col-xs-4"&gt;
              &lt;input type="text" class="form-control" readonly formControlName="detailName"&gt;
          &lt;/div&gt;
          &lt;div class="col-xs-3"&gt;
              &lt;input type="text" class="form-control" readonly formControlName="detailCountry"&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>On <code>change</code> of textbox value, I'm calling the function <code>getAccountAssociatedDetails</code>, as you can see. If there are some details associated with the value entered, I'm replacing that current <code>FormGroup</code> and adding some more <code>FormGroup</code>s to the row.</p>
  
  <pre><code>getAccountAssociatedDetails(control: FormControl, type: string, index: number) {
      let value = control.value;
      if (!!value) {
          let form = this.detailForm;
          control.setErrors({
              'alreadyEntered': null
          });
  
          if (type === 'detail') {
              if (this.detailAlreadyEnteredManually.detailNo.includes(value)) {
                  control.setErrors({
                      'alreadyEntered': true
                  });
              }
          } else if (type === 'account') {
              if (this.detailAlreadyEnteredManually.accountNumber.includes(value)) {
                  control.setErrors({
                      'alreadyEntered': true
                  });
              }
          }
  
          // if detail or account is already entered dont call service
          if (!control.hasError('alreadyEntered')) {
              this.agreementDetailsService.getdetails(value, type)
                  .subscribe(response =&gt; {
                          let associatedDetailsArray = &lt; Array &lt; any &gt;&gt; response;
                          if (!!associatedDetailsArray) {
                              let rows = &lt; FormArray &gt; form.get('rows');
  
                              // if search mode is 'detail'
                              if (type === 'detail') {
                                  if (!this.detailAlreadyEnteredManually.detailNo.includes(value)) {
                                      rows.setControl(index, this.builddetailItem(associatedDetailsArray[0].accountNumber.value, value, associatedDetailsArray[0].detailName, associatedDetailsArray[0].detailCountry));
                                      this.detailAlreadyEnteredManually.detailNo.push(value);
  
                                      for (let i = 1; i &lt; associatedDetailsArray.length; i++)
                                          rows.insert(index + i, this.builddetailItem(associatedDetailsArray[i].accountNumber.value, value, associatedDetailsArray[i].detailName, associatedDetailsArray[i].detailCountry));
                                  }
  
                                  //if search mode is 'account'
                              } else if (type === 'account') {
                                  if (!this.detailAlreadyEnteredManually.accountNumber.includes(value)) {
                                      rows.setControl(index, this.builddetailItem(value, associatedDetailsArray[0].detailNo.value, associatedDetailsArray[0].detailName, associatedDetailsArray[0].detailCountry));
                                      this.detailAlreadyEnteredManually.accountNumber.push(value);
  
                                      for (let i = 1; i &lt; associatedDetailsArray.length; i++)
                                          rows.insert(index + i, this.builddetailItem(value, associatedDetailsArray[i].detailNo.value, associatedDetailsArray[i].detailName, associatedDetailsArray[i].detailCountry));
                                  }
                              }
                          }
                      },
                      error =&gt; console.log(error));
          }
      }
  }
  </code></pre>
  
  <p>The last two fields in the <code>FormGroup</code> are <code>readonly</code> by default. Once the user enters something in either of the first two fields and focuses out, the details associated with that value should be fetched, the current <code>FormGroup</code> is replaced and other <code>FormGroup</code>s in the generated list are appended. I want all the <code>FormControl</code>s in those newly added <code>FormGroup</code>s should be <code>readonly</code>. The user can add more fields and the process repeats.</p>