3
import {Component} from "angular2/core";
import {CORE_DIRECTIVES, FORM_DIRECTIVES, FormBuilder, ControlGroup, AbstractControl, Validators, Control} from "angular2/common";

@Component({
    selector: 'parameters-form',
    directives: [FORM_DIRECTIVES,CORE_DIRECTIVES],
    template: `
      <h1>Parameters Form</h1>
      <p [(ngModel)]='arr'>{{ arr }}</p>
      <form [ngFormModel]="myForm" (ngSubmit)="onSubmit(myForm.value)"    class="ui form">

<div class="field">
            <label for="systemParameters">System Parameters</label>
            <input type="number"
                   id="systemParameters"
                   placeholder="systemParameters Param"
                   [ngFormControl]="systemParameters">

            <button type="button" (click)="addToArray(systemParameters.value)">Add</button>

          </div>
<button type="submit" class="ui button">Submit</button>
      </form>
    `
})

export class ParametersForm {
  myForm: ControlGroup;
  systemParameters: AbstractControl;
  arr: number[];
  constructor(fb: FormBuilder) {
    this.myForm = fb.group({
      "realisations" : [""],
      "numConstSteps" : [""],
      "timeHorizon": [""],
      "continuationStep" : [""],
      "continuationStepSign" : [""],
      "numberOfModelParameters" : [""],
      "systemParameters" : [],
      "param" : [""],
      "netLogoFile" : [""],
      "numberOfModelVariables" : [""],
      "restrictOperator" : [""],
      "liftOperator" : [""],
      "xInitial" : [""]

    });
    this.arr = [];
    this.systemParameters = this.myForm.controls["systemParameters"];
  }
  addToArray(value: any): void {
    this.arr.push(value);
    (<Control>this.systemParameters).updateValue("");
  }
  onSubmit(form: any): void {
    console.log(this.arr);
    form.systemParameters = this.arr;
    console.log("your submitted value:", form)
  }

}

i am trying to show the values inside Arr (array) in real-time, when user inputs value in systemParameters field by invoking the Add function which pushes the value to arr array.

this is the error No value accessor for ''" in [arr in ParametersForm@2:9]

its cause from the ngModel thats as much as i know.

Updated: based on Günter's comments I removed both ngModel and Core directives. The {{arr}} contents do not show but internally in the class they do.

SnareChops
  • 13,175
  • 9
  • 69
  • 91
Petros Kyriakou
  • 5,214
  • 4
  • 43
  • 82
  • You shouldn't need to add `CORE_DIRECTIVES` anymore. See http://stackoverflow.com/questions/34496514/ngmodel-no-value-accessor-for for a similar question. Can you provide a plunker? – Günter Zöchbauer Feb 14 '16 at 17:00
  • You can't use `ngModel` like that on a `p` element. `ngModel` is for input elements. – Günter Zöchbauer Feb 14 '16 at 17:06
  • @GünterZöchbauer ah here is a plunker `http://plnkr.co/edit/dHJf8QEhhvU5LupdDcmX?p=preview` so what can i do to show the array values in real time? – Petros Kyriakou Feb 14 '16 at 17:16
  • Thanks. Still, what's the point of adding `[(ngModel)]` on a `

    – Günter Zöchbauer Feb 14 '16 at 17:17
  • @GünterZöchbauer i am just tring to figure out how to show the values of the array as said and the only thing i saw that can mimick this functionality is ngModel i guess - i am new at angularjs 2 really so you could say i am fiddling about while having a specific project in mind.. – Petros Kyriakou Feb 14 '16 at 17:19
  • 1
    Just remove the `[(ngModel)]` there. It doesn't do anything. – Günter Zöchbauer Feb 14 '16 at 17:20
  • Removed both ngModel and Core directives now. tried it without ngModel as well. the arr content do not show but internally in the class they do. – Petros Kyriakou Feb 14 '16 at 17:23

2 Answers2

4

Update: As of beta.16, {{myArray}} will now update in the view, even if the array reference hasn't changed. See also {{myArray}} now updates in the view as of beta.16


Original answer:

Angular change detection compares by value, and for arrays and objects, that means the array or object reference. If your view simply has {{arr} in it, then that binding in the view won't update when you push() items onto the array, because the array reference hasn't changed.

However, normally, a template will loop over the items in an array:

<div *ngFor="item of arr">{{item}}</div>

In this case, Angular change detection will have a binding for each item of the array, so push() updates will be noticed, and the view will be updated.

For debugging, if you instead use {{arr | json}}, you'll also see the view update when you push() onto the array. (This is because the JsonPipe is stateful, which causes Angular change detection to evaluate it every change detection cycle.)

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • thanks for your input this seems like the best practice so i marked this as the correct answer for future reference. One question though, why is `{{arr | json}}` only for debugging? – Petros Kyriakou Feb 15 '16 at 19:26
  • @PetrosKyriakou, because normally you don't want to show a string version of an array or object to your users. – Mark Rajcok Feb 15 '16 at 21:19
1

Angular change detection doesn't recognize changes within arrays, only changes to the array reference

  addToArray(value: any): void {
    // Angular doesn't recognize this
    this.arr.push(value);
    (<Control>this.systemParameters).updateValue("");
  }

as workaround you can use

  addToArray(value: any): void {
    this.arr.push(value);
    this.arr = this.arr.slice();
    (<Control>this.systemParameters).updateValue("");
  }

to create a copy of the array. Angular recognizes this because the array itself is another one.

Checking for a better way ...

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • hmm updated plunker with this, but it says [object, mousevent] ? – Petros Kyriakou Feb 14 '16 at 17:32
  • 1
    ah nvm i had this `addToArray($event, systemParameters.value)` in my local code after i fiddled some more with the code which is not present here in stackoverflow post, removed it and now shows values, thank you! – Petros Kyriakou Feb 14 '16 at 17:35
  • I agree with what you said, but I think you may confuse people by saying that "Angular change detection doesn't recognize changes within arrays", because normally there is an `NgFor` associated with the array in the template, and change detection will then recognize changes to the items. See my answer for more details. – Mark Rajcok Feb 15 '16 at 18:01
  • @MarkRajcok thanks for the feedback. I remember you mentioning it recently. – Günter Zöchbauer Feb 15 '16 at 18:48