0

I'm trying to get radio button value and send them to MySql database but i got an error that said TypeError: Cannot read property 'value' of undefined. I'm using Angular and express JS in this project. In the server side, the query is looks like this app.post('/post', ...){ let sql = 'INSERT INTO results(question1, question2, question3)values("'+req.body.question1+'", "'+req.body.question2+'", "'+req.body.question3+'")'; }. I already have the questions and the options in a json file.

//data.json

[{
  "surveyid": 101,
  "surveyname": "Vitamin",
  "createdby": "Dr. Sarah",
  "createddate": "16-01-2018",
  "question": [{
      "questionid": 1,
      "questiondesc": "Q-1?",
      "qno": 1,
      "alloptions": [{
          "options": "A",
          "answer": "Yes"
        },
        {
          "options": "B",
          "answer": "No"
        }
      ]
    },

    {
      "questionid": 2,
      "questiondesc": "Q_2?",
      "qno": 2,
      "alloptions": [{
          "options": "A",
          "answer": "Yes"
        },
        {
          "options": "B",
          "answer": "No"
        },
        {
          "options": "C",
          "answer": "Don't know"
        }
      ]
    },

    {
      "questionid": 3,
      "questiondesc": "Q_3",
      "qno": 1,
      "alloptions": [{
          "options": "A",
          "answer": "Yes"
        },
        {
          "options": "B",
          "answer": "No"
        }
      ]
    }
  ]
}]

And then i load all the questions and options into html template.

<form>
  <div *ngFor="let items of jsonData">
    <div *ngFor="let items2 of items.question">
      <label>{{items2.questionid}}. {{items2.questiondesc}}</label>
      <div *ngFor="let items3 of items2.alloptions; let idx=index">
        <div class="radio">
          <input type="radio" name="question{{items2.questionid}}" [value]="items3.answer"><b>{{items3.options}}</b>. {{items3.answer}}
        </div>
      </div><br>
    </div>
  </div>
  <div align="center">
    <button type="button" class="btn btn-sm btn-success" (click)="pushResults(question1.value, question2.value, question3.value)">SUBMIT</button>
  </div>
</form>

And here is the service and component

//service.ts
getJsonData(): Observable < any > {
  return this.http.get('../assets/data.json')
    .map((res: Response) => res.json())
    .catch((error: any) => Observable.throw(error.json().error || 'server returns error'))
}

pushResults(question1: string, question2: string, question3: string) {
  return this.http.post('http://localhost:8000/newPush', {
    question1: question1,
    question2: question2,
    question3: question3
  });
}

//component.ts
jsonData = [];
getJsonData() {
  this.AppService.getJsonData().subscribe(
    data => console.log('json', this.jsonData = data),
    error => console.log('server returns error')
  );
}

pushResults(question1: string, question2: string, question3: string) {
  this.AppService.pushResults(question1, question2, question3);
}

Can anyone help me with this, please? Please let me know if more snippets are needed.

1
  • Answered in this Link. Thank you. Commented Jan 19, 2018 at 5:59

2 Answers 2

1

Since you don't use angular forms you can obtain values through form elements collection:

First thing you need to do is to get hold of form element.

<form #myForm>

Now you can access the value of the elements like this:

form.elements['question1'].value

Native Form Example

Angular template driven form

1) Import FormsModule to your NgModule

import { FormsModule } from '@angular/forms';    

@NgModule({
  imports: [
    ...
    FormsModule
  ],
  ...
})
export class AppModule { }

2) Create property of type Array in your component

answers: string[] = [];

3) Change template like:

<form #form="ngForm">
  <div *ngFor="let items of jsonData">
    <div *ngFor="let items2 of items.question; let i = index">
      <label>{{items2.questionid}}. {{items2.questiondesc}}</label>
      <div *ngFor="let items3 of items2.alloptions; let idx=index">
        <div class="radio">
          <input type="radio" 
            name="question{{items2.questionid}}"
            [(ngModel)]="answers[i]"                     
            [value]="items3.answer"><b>{{items3.options}}</b>. {{items3.answer}}
        </div>
      </div><br>
    </div>
  </div>
  <div align="center">
    <button type="button" class="btn btn-sm btn-success" (click)="pushResults(form.value)">
      SUBMIT
    </button>
  </div>
</form>
<pre>{{ form.value | json }}</pre>

Template driven Form Example

Angular model driven Form

1) Import ReactiveFormsModule to your NgModule

import { ReactiveFormsModule} from '@angular/forms';    

@NgModule({
  imports: [
    ...
    ReactiveFormsModule
  ],
  ...
})
export class AppModule { }

2) Create FormGroup in your component

import { FormGroup, FormBuilder } from '@angular/forms';

@Component({
  ...
})
export class AppComponent {

  form: FormGroup;
  ...

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.fb.group({
      question1: '',
      question2: '',
      question3: ''
    })
  }

  pushResults(formValue) {
    console.log(formValue.question1, formValue.question2, formValue.question3);
  }
}

3) Change template like:

<form [formGroup]="form">
  <div *ngFor="let items of jsonData">
    <div *ngFor="let items2 of items.question; let i = index">
      <label>{{items2.questionid}}. {{items2.questiondesc}}</label>
      <div *ngFor="let items3 of items2.alloptions; let idx=index">
        <div class="radio">
          <input type="radio" 
              name="question{{items2.questionid}}"  
              formControlName="question{{i+1}}"
              [value]="items3.answer"><b>{{items3.options}}</b>. {{items3.answer}}
        </div>
      </div><br>
    </div>
  </div>
  <div align="center">
    <button type="button" class="btn btn-sm btn-success" (click)="pushResults(form.value)">
      SUBMIT
  </button>
  </div>
</form>
<pre>{{ form.value | json }}</pre>

Model driven Form Example


If you want to do only one form you do not need to import FormsModule or ReactiveFormsModule but for scale project I would suggest using one of angular built-in methods.

Sign up to request clarification or add additional context in comments.

Comments

1

Don't use this inside templates. this is only meant to be used inside components. Because inside templates all the variables you use are meant to be component/class variables. Local variables can't be referenced in templates. Directly access the member variable as follows:

(click)="pushResults(question1.value, question2.value, question3.value)"

2 Comments

thanks, updated my code, but still got the same error.
check the answer to your other question: stackoverflow.com/a/48334015/5346095 It may help. Else console the values your pushing function receives. Share the same in plunk.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.