0

I have created a form in which I would like users to select the room that they want, among other things. If I do this as a dropdown or as an input type in which they type in the information, it is submitted via email through PHP.

However, if I change the input type to "hidden", the value completely disappears and what I see in the console is this:

<input _ngcontent-c4 name="room" type="hidden" value class="ng-untouched ng-pristine ng-valid">

Then, in the Network, nothing appears as an object for "room". (Note: other objects do appear.)

Then, if I simply change the style to "display: none;" and put the value="ChosenRoom", nothing is sent in the email. In fact, despite showing up clearly in the console as

<input _ngcontent-c4 name="room" style="display: none;" type="text" value="ChosenRoom" class="ng-untouched ng-pristine ng-valid">

the object doesn't show up in the network.

Any idea what could be the problem?

CODE:

(I have posted it in a rudimentary Plunker as well: http://embed.plnkr.co/uUhPrStdw4kDhaus2xfO/)

This one works, but the user has to type in the room name in the form:

HTML (Note: I left out the remaining code for the form, assuming that it isn't relevant in this case. If you think this would help, I'd be happy to post that as well.)

<form (submit)="sendEmail(message)" #f="ngForm">
    <input type="text" name="room" [(ngModel)]="message.room" #room="ngModel">
    <button type="submit" [disabled]="f.invalid" *ngIf="!f.submitted">
</form>

HTML - This one doesn't show the value in the console.

<form (submit)="sendEmail(message)" #f="ngForm">
    <input type="hidden" name="room" [(ngModel)]="message.room" #room="ngModel" value="ThisRoom">
    <button type="submit" [disabled]="f.invalid" *ngIf="!f.submitted">
</form>

HTML - This one shows the value in the console, but does not show any object in the Network.

<form (submit)="sendEmail(message)" #f="ngForm">
    <input type="text" style="display: none;" name="room" [(ngModel)]="message.room" #room="ngModel" value="ThisRoom">
    <button type="submit" [disabled]="f.invalid" *ngIf="!f.submitted">
</form>

Typescript: Contact.Service.TS

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Resolve } from '@angular/router';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

export interface IMessage {
  name?: string,
  email?: string,
  room?: string,
  daterange?: string,
  message?: string
}

@Injectable()
export class AppService {
  private emailUrl = '/assets/email.php';

  constructor(private http: Http) {

  }

  sendEmail(message: IMessage): Observable<IMessage> | any {
    return this.http.post(this.emailUrl, message)
      .map(response => {
        console.log('Sending email was successfull', response);
        return response;
      })
      .catch(error => {
        console.log('Sending email got error', error);
        return Observable.throw(error)
      })
  }
}

PHP

<?php

header('Content-type: application/json');

$errors = '';

if(empty($errors))
{

    $postdata = file_get_contents("php://input");
    $request = json_decode($postdata);


    $from_email = '[email protected]';
    $message = $request->message;
    $from_name = $request->name;

    $to_email = "[email protected]";

    $contact = "<p><strong>Name:</strong> $from_name</p>
                <p><strong>Email:</strong> $request->email</p>
                <p><strong>Room:</strong> $request->room</p>
                <p><strong>Dates:</strong> $request->daterange</p>";
    $content = "<p><strong>Message:</strong><p>$message</p>";




    $website = 'My Currently Not but soon to be Functioning Website';
    $email_subject = "$website: Received a message from $from_name";

    $email_body = '<html><body>';
    $email_body .= "$contact $content";
    $email_body .= '</body></html>';

    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
    $headers .= "From: $from_email\n";
    $headers .= "Reply-To: $from_email";

    $result = mail($to_email,$email_subject,$email_body,$headers);

    $response_array['status'] = 'success';
    $response_array['from'] = $from_email;
    $response_array['result'] = $result;

    echo json_encode($response_array);

    header($response_array);
    return $from_email;
} else {
    $response_array['status'] = 'error';
    echo json_encode($response_array);
    header('Location: /error.html');
}
?>

I appreciate any help or ideas.

Thanks!

Brad

3
  • 1
    Is the hidden value included in Angular though? If not, could you try and reproduce the issue in a plunker, since I could include the hidden field just fine in the angular code. Commented Jun 9, 2017 at 12:15
  • Good idea @AJT_82 I have added a rudimentary Plunker to the post. I have found an alternative solution that avoids the hidden field problem. So, I'm not sure if I can actually do a hidden field or not. Commented Jun 9, 2017 at 16:38
  • This has nothing to do with it actually being hidden. ngModel overrides value. Also it doesn't really make even sense to have two-way-binding, since you could very well get the same object from the form :) Also, in this case I'd maybe suggest a model-driven-form, the hidden property would be easy to create with that :) If you want to stick to the template-driven form, I'd suggest you set the default value to the room instead. Commented Jun 9, 2017 at 17:15

2 Answers 2

1

I have found one solution for this problem. It completely avoids the hidden fields, which I'm still not sure if they were the problem or not.

Working Solution:

contact.component.html - Here, I avoid the hidden input and pass the text beside the message. Pay special attention to 'This particular room'

<form (submit)="sendEmail(message, 'This particular room')" #f="ngForm">
...
</form>

contact.component.ts - Pay special attention to message.room = room;

import { Component, OnInit, HostBinding } from '@angular/core';
import { AppService, IMessage } from '../../contact/contact.service';

@Component({
  selector: 'app-contact',
  templateUrl: './contact.component.html',
  styleUrls: ['./contact.component.css']
})
export class TheensuiteComponent implements OnInit {
    message: IMessage = {};

  constructor(private appService: AppService) { }

  sendEmail(message: IMessage, room:string) {
    message.room = room;
    this.appService.sendEmail(message).subscribe(res => {
      console.log('ContactComponent Success', res);
    }, error => {
      console.log('ContactComponent Error', error);
    })
  }

  ngOnInit() {
    };
  }
}

Everything else is left the same (contact.service.ts and email.php).

This is, of course, a slight hack. If I wanted to pass more information, this could cause jumbled code pretty quickly.

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

Comments

0

First of all, that the value is not added, is because ngModel overrides value and therefore has nothing to do with the fact that is hidden. Secondly I would suggest that you might want to use a model-driven form here. Sometimes a model-driven form is overkill, but in this case I'd use one. So I'd thought I'd throw in that option for you, if you want to consider it.

You need to import ReactiveFormsModule and add it to your imports array in your ngModule. Then import the following to your component and inject FormBuilder in your constructor:

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

constructor(private fb: FormBuilder) {}

Then build the form with the validators you want:

this.myForm = this.fb.group({
  room: ['theEnsuite'],
  name: ['', Validators.required],
  email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$']],
  message: ['', [Validators.required, Validators.minLength(10)]]
})

and then you can get rid of the two-way binding and exchange it with form control instead. The good thing is, that you do not need to include the room at all in your template. It is nicely already sitting in the form object :) Here's a sample of the name input with error message:

<input placeholder="Name" formControlName="name">
<div *ngIf="!myForm.get('name').valid && myForm.get('name').touched">
  <p>Please enter your name.</p>
</div>

When you submit the form you do it with myForm.value as parameter. That object then is identical to your object of type IMessage, which you can use the post request directly with this object!

Here's a DEMO of the above.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.