*Goal :*
     I was doing this task as a part of ann assignment of an online course 
portal.
    Task 4

In this task you will use animation together with a progress spinner and 
the fact that the post() method will return the submitted feedback object 
as a return value to display briefly the submitted data to confirm the form 
submission to the user:

   - When the form is submitted, you should hide the form and display the 
   progress spinner until the server responds confirming the update on the 
   server side. See the next point below for further details.
   - Recall how in the lesson on saving data to the server, the PUT request 
   returns an observable that we subscribe and then use the updated dish data 
   returned to update the dish object in dishdetail.component.ts. Similarly 
   when you do a post(), the feedback service must return the feedback object 
   returned from the server after submission, by the submitFeedback() method. 
   You can then subscribe to it within the contact.component.ts to obtain the 
   returned feedback object. This confirms the successful submission of the 
   feedback to the server.
   - After obtaining the confirmation from the server within the 
   subscribe() method above, you should then display the information from the 
   returned feedback object in the format as shown in the video for 5 seconds. 
   Thereafter you should hide this and then again show the empty form to the 
   user enabling them to submit the feedback again. Hint: Leverage the 
   setTimeout() method for this purpose.
   - Use the expand animation that we have already used earlier to 
   judiciously apply animation to the various stages of the form submission.

  What I am trying to do
    I have done some coding and have attached the .ts and .html files
What i am getting
  I am getting error as follows --
    compiler.js:20600 Uncaught Error: Template parse errors:
Assigning animation triggers via @prop="exp" attributes with an expression 
is invalid. Use property bindings (e.g. [@prop]="exp") or use an attribute 
without a value (e.g. @prop) instead. ("
    <mat-spinner></mat-spinner>
  </div>
  <div fxflex  *ngif="feedback && submitted" [ERROR ->]@expand]=" ">   
    <mat-list >
      <h3>Your Submission</h3>
"): ng:///AppModule/ContactComponent.html@94:45
Can't bind to 'ngif' since it isn't a known property of 'div'. ("
    <mat-spinner></mat-spinner>
  </div>
  <div fxflex  [ERROR ->]*ngif="feedback && submitted" @expand]=" ">   
    <mat-list >
      <h3>Your Submission</h3>
"): ng:///AppModule/ContactComponent.html@94:15
Property binding ngif not used by any directive on an embedded template. 
Make sure that the property name is spelled correctly and all directives 
are listed in the "@NgModule.declarations". ("
    <mat-spinner></mat-spinner>
  </div>
  [ERROR ->]<div fxflex  *ngif="feedback && submitted" @expand]=" ">   
    <mat-list >
      <h3>Your Submission"): ng:///AppModule/ContactComponent.html@94:2
    at syntaxError (compiler.js:2426)
    at 
TemplateParser.push../node_modules/@angular/compiler/fesm5/compiler.js.TemplateParser.parse
 
(compiler.js:20600)
    at 
JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._parseTemplate
 
(compiler.js:26146)
    at 
JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileTemplate
 
(compiler.js:26133)
    at compiler.js:26076
    at Set.forEach (<anonymous>)
    at 
JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileComponents
 
(compiler.js:26076)
    at compiler.js:25986
    at Object.then (compiler.js:2417)
    at 
JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents
 
(compiler.js:25985)
What do I want
  I want to know why I am getting this error and how to fix it. I have 
debugged ithe code many times but wasn't able to find where i am going 
wrong so please tell me complete solution for this. i am new to angular.

-- 
You received this message because you are subscribed to the Google Groups 
"Angular and AngularJS discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Feedback,ContactType } from '../shared/feedback';
import { map, catchError } from 'rxjs/operators';
import { ProcessHTTPMsgService } from './process-httpmsg.service';
import { baseURL } from '../shared/baseurl';
import { HttpClient, HttpErrorResponse, HttpHeaders,HttpSentEvent } from '@angular/common/http';

const HttpUploadOptions = {
  headers: new HttpHeaders({ "Content-Type": "application/json"  })
}
@Injectable({
  providedIn: 'root'
})
export class FeedbackService {

  constructor(private http: HttpClient, private processHTTPMsgService: ProcessHTTPMsgService) { }
  submitFeedback(feedback : Feedback):Observable<Feedback>{
    return this.http.post<Feedback>((baseURL + 'feedback'), feedback, HttpUploadOptions)
    .pipe(
      catchError(this.processHTTPMsgService.handleError)   
       );
    
  

  }
}
import { Component, OnInit, ViewChild } from '@angular/core';
import { Params, ActivatedRoute } from '@angular/router'; 
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FeedbackService } from '../services/feedback.service';
import { Feedback, ContactType } from '../shared/feedback';
import { flyInOut, expand } from '../animations/app.animation';
import { visibility } from '../animations/app.animation';
import { switchMap } from 'rxjs/operators';
@Component({
  selector: 'app-contact',
  templateUrl: './contact.component.html',
  styleUrls: ['./contact.component.scss'],
  host: {
    '[@flyInOut]': 'true',
    'style': 'display: block;'
    },
    animations: [
      flyInOut(),
      expand(),
      visibility()
    ]
})
export class ContactComponent implements OnInit {
  submitted: boolean;
  feedbackForm: FormGroup;
  feedback: Feedback;
  feedbackService :FeedbackService;
  contactType = ContactType;
  errMess: string;
  visibility = 'shown';
  constructor(private fb: FormBuilder,private feedbackservice :FeedbackService) {
    this.createForm();
  }
  @ViewChild('fform') feedbackFormDirective;
  formErrors = {
    'firstname': '',
    'lastname': '',
    'telnum': '',
    'email': ''
  };
  
  validationMessages = {
    'firstname': {
      'required':      'First Name is required.',
      'minlength':     'First Name must be at least 2 characters long.',
      'maxlength':     'FirstName cannot be more than 25 characters long.'
    },
    'lastname': {
      'required':      'Last Name is required.',
      'minlength':     'Last Name must be at least 2 characters long.',
      'maxlength':     'Last Name cannot be more than 25 characters long.'
    },
    'telnum': {
      'required':      'Tel. number is required.',
      'pattern':       'Tel. number must contain only numbers.'
    },
    'email': {
      'required':      'Email is required.',
      'email':         'Email not in valid format.'
    },
  };

  ngOnInit() {
  }
  
  createForm() {
    this.feedbackForm = this.fb.group({
      firstname: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(25)] ],
      lastname: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(25)] ],
      telnum: ['', [Validators.required, Validators.pattern] ],
      email: ['', [Validators.required, Validators.email] ],
      agree: false,
      contacttype: 'None',
      message: ''
    });

    this.feedbackForm.valueChanges
    .subscribe(data => this.onValueChanged(data));

  this.onValueChanged(); // (re)set validation messages now

  }
  onValueChanged(data?: any) {
    if (!this.feedbackForm) { return; }
    const form = this.feedbackForm;
    for (const field in this.formErrors) {
      if (this.formErrors.hasOwnProperty(field)) {
        // clear previous error message (if any)
        this.formErrors[field] = '';
        const control = form.get(field);
        if (control && control.dirty && !control.valid) {
          const messages = this.validationMessages[field];
          for (const key in control.errors) {
            if (control.errors.hasOwnProperty(key)) {
              this.formErrors[field] += messages[key] + ' ';
            }
          }
        }
      }
    }
  }

  onSubmit() {
    this.submitted = true;
    this.feedback = this.feedbackForm.value;
    console.log(this.feedback);
    this.feedbackService.submitFeedback(this.feedback)
    .subscribe(data => {
      this.feedback = data,
      // after 5s form becomes not submitted (visible)
      setTimeout(() => {
        this.submitted = false; }, 5000); },
    errmess => { this.feedback = null; this.errMess = <any>errmess; });
    this.feedbackForm.reset({
      firstname: '',
      lastname: '',
      telnum: '',
      email: '',
      agree: false,
      contacttype: 'None',
      message: '',
    });
    this.feedbackFormDirective.resetForm();
  }
  
}

Contact Us


Location Information

Our Address

121, Clear Water Bay Road
Clear Water Bay, Kowloon
HONG KONG
: +852 1234 5678
: +852 8765 4321
: [email protected]

Map of our Location

Send us your Feedback

{{ feedbackForm.value | json }} {{ feedbackForm.status | json }}

{{formErrors.firstname}} {{formErrors.lastname}}

{{formErrors.telnum}} {{formErrors.email}}

May we contact you? {{ ctype }}

Submitting Form

Your Submission

First Name: {{feedback.firstname}}

Last Name: {{feedback.lastname}}

Tel. Number: {{feedback.telnum}}

Email: {{feedback.email}}

Contact You?: {{feedback.agree}}

How?: {{feedback.contacttype}}

Feedback: {{feedback.message}}

import { trigger, state, style, animate, transition } from '@angular/animations';

export function visibility() {
    return trigger('visibility', [
        state('shown', style({
            transform: 'scale(1.0)',
            opacity: 1
        })),
        state('hidden', style({
            transform: 'scale(0.5)',
            opacity: 0
        })),
        transition('* => *', animate('0.5s ease-in-out'))
    ]);
}
export function flyInOut() {
    return trigger('flyInOut', [
        state('*', style({ opacity: 1, transform: 'translateX(0)'})),
        transition(':enter', [
            style({ transform: 'translateX(-100%)', opacity: 0 }),
            animate('500ms ease-in')
        ]),
        transition(':leave', [
            animate('500ms ease-out', style({ transform: 'translateX(100%)', opacity: 0}))
        ])
    ]);
}

export function expand() {
    return trigger('expand', [
        state('*', style({ opacity: 1, transform: 'translateX(0)' })),
        transition(':enter', [
            style({ transform: 'translateY(-50%)', opacity:0 }),
            animate('200ms ease-in', style({ opacity: 1, transform: 'translateX(0)' }))
        ])
    ]);
}