3

For the life of me, it seems like I should be able to create a disabled FormArray. I'm trying to build a view-only parent form (FormArray) with 1-n subarrays (also FormArray). I pass the subarrays down to the child components to initialize their controls (FormControl).

I've tried calling disable() on the parent form with different options and at different hooks of the life cycle, it throws this exception:

Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.

Here's are a couple examples of some of what I've tried:

  • in ngOnInit, both create and disable form -> does not disable, throws exception
  • in ngOnInit create form, in ngAfterViewInit disable form -> DOES disable but throws exception

An older version of forms accepted an options object, and (sadly) this no longer works but would have looked like: new FormArray({ value: myControlsArray, disabled: true }).

I created a plnkr to model the component hierachy and form.

Does anyone know how to initialize a disabled form?


Edit (answer): I overlooked an important piece of information and clue to the solution. In my use case, I take a saved form value and initialize a new read-only form. Instead of passing the saved form value to the child component, I instead should have created the parent form and its sub-forms and controls.

stealththeninja
  • 3,576
  • 1
  • 26
  • 44
  • you can't create disabled form, first you should create it then disable. – Roman C Feb 09 '17 at 19:08
  • @RomanC I hope my question made it clear that's the current method I'm using. Please note the change detection exception it's causing. Ideally there would be a way to initialize the form in a disabled state, but realistically I need help figuring out where/how to call the `disable()` method so it doesn't trip up change detection. – stealththeninja Feb 09 '17 at 19:22

2 Answers2

1

You can't create a disabled form. But you can create a disable set of input (fieldset), which turns out to be the same if your group is as big as the form.

<fieldset [disabled]=[true]>
  <input type="text" ...>
  <input ...>
</fieldset>

See There is some way to disabled set of inputs in angular 2?

Community
  • 1
  • 1
zurfyx
  • 31,043
  • 20
  • 111
  • 145
  • Although clever and a good reminder on HTML basics, this didn't solve my problem. Angular 2 didn't bind the `disabled` attribute on the `
    ` to my form so while functionally disabled, they didn't apply visual styling for the disabled state.
    – stealththeninja Feb 10 '17 at 06:16
0

As noted in the edit, I'm using a saved form value to initialize a new read-only form. Rather than pass the value to the child component to initialize its controls, I solved this in large part by constructing the controls at the same time as the parent form and sub-forms. Doing so I could disable the parent form in ngOnInit without tripping change detection and still pass the sub-forms down to the child components. Here's an excerpt of what it looked like and the working example:

app.component.ts:

public questions: Array<string[]> = MULTIPLE_RADIOS;

public responses: Array<string[]> = MULTIPLE_RESPONSES;

constructor(private _fb: FormBuilder) {}

ngOnInit() {
    this.form = this._fb.array([]);
    for (let response of this.responses) {
      const questionForm = this._fb.array([]);
      for (let responseControl of response) {
        questionForm.push(this._fb.control(responseControl));
      }
      this.form.push(questionForm);
    }
    this.form.disable({ emitEvent: false });
  }

app-radio.component.ts:

@Input()
public form: FormArray;

@Input()
public radios: string[];

constructor(private _fb: FormBuilder) {}

ngOnChanges() {
  // same component used to create a live form
  // in this case, its parent (app-question.component) gives
  // it an empty form, and the child adds the control it needs
  if (this.form.length === 0) {
    this.form.push(this._fb.control(''));
  }
}
stealththeninja
  • 3,576
  • 1
  • 26
  • 44