5

I have a long list of user inputs, and would like to store these in an object instead of spelling them out in HTML. I want to bind these values to another object that stores the user/customer's data. Preferably using ngModel due to its simplicity and functionality.

Anyone knows how I can achieve this?

Example below (not working).

@Component({
  template: `
    <div>
      <h2>NgModel Example</h2>
      <div *ngFor="let input of inputList">
        {{ input.label }} <input type="text" [(ngModel)]="input.bindTo">
      </div>
    </div>

    <p>This is not working: {{customerInfo.name}}, {{customerInfo.email}}</p>
  `,
  directives: [...]
})

export class AppComponent {
  inputList = [
    {
      label: "Enter your name",
      bindTo: this.customerInfo.name  // also tried 'customerInfo.name'
    },
    {
      label: "Enter your email",
      bindTo: this.customerInfo.email
    }
  ]  

  customerInfo = {
    name: 'test',
    email: ''
  }
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Daniel Mattsson
  • 676
  • 2
  • 8
  • 9

1 Answers1

12

That's not supported. ngModel can only bind to a property of the component. I also don't see a way to refer to a component property by a string literal from the template without helper methods:

This might work for you:

  <div *ngFor="#input of inputList">
    {{ input.label }} 
    <input type="text" 
        [ngModel]="getProp(input.bindTo)" 
        (ngModelChange)="setProp(input.bindTo, $event)">
  </div>
  inputList = [
    {
      label: "Enter your name",
      bindTo: "name"
    },
    {
      label: "Enter your email",
      bindTo: "email"
    }
  ];

  getProp(prop) {
    return this[prop];
  }

  setProp(prop, value) {
    this[prop] = value;
  }

  <div *ngFor="#input of inputList; #i = index">
    {{ input.label }} <input type="text" [(ngModel)]="inputList[i]">
  </div>

hint for => RC.0 # should be replaced by let

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • But I want to bind to customerInfo, which is a property of the component? Also - did you mean to write `[(ngModel)]="inputList[i].bindTo"` ? – Daniel Mattsson Jun 02 '16 at 06:14
  • I don't see `customInfo` being related to `ngModel` in your question. Oh, just saw. It seems `bindTo` is supposed to cause a further redirect. – Günter Zöchbauer Jun 02 '16 at 06:17
  • Thanks a lot, with slight modifications it worked! Essentially, this[prop] didn't work if prop was using dot-notation. I fixed it in an ugly way like this `setProp(prop, value) { this['customerInfo'][prop] = value; }` Will try to find a better solution that works with dot-notation, but this definitely steered me in the right direction - thanks! – Daniel Mattsson Jun 02 '16 at 06:36
  • Glad to hear. Thanks for the feedback. I'm not native JS/TS developer. I'm sure there are lots of StackOverflow questions covering that topic. Like http://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference – Günter Zöchbauer Jun 02 '16 at 06:39