简体   繁体   中英

How to properly move function from component.ts to a service file?

I wrote a function in my component.ts which sends PUT request. It works as it should, but I want to move the function to a service.ts file. I moved it but it doesn't work. When I click "Save", it shows an error in console:

FormsComponent.html:32 ERROR TypeError: _co.editForm is not a function at Object.eval [as handleEvent] (FormsComponent.html:32) at handleEvent (core.js:23008) at callWithDebugContext (core.js:24078) at Object.debugHandleEvent [as handleEvent] (core.js:23805) at dispatchEvent (core.js:20457) at core.js:20904 at HTMLButtonElement. (platform-browser.js:993) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423) at Object.onInvokeTask (core.js:17279) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422) View_FormsComponent_0 @ FormsComponent.html:32 proxyClass @ compiler.js:18234 push../node_modules/@angular/core/fesm5/core.js.DebugContext_.logError @ core.js:24040 push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @ core.js:15761 dispatchEvent @ core.js:20461 (anonymous) @ core.js:20904 (anonymous) @ platform-browser.js:993 push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:423 onInvokeTask @ core.js:17279 push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:422 push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:195 push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:498 invokeTask @ zone.js:1744 globalZoneAwareCallback @ zone.js:1770 FormsComponent.html:32 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 31, nodeDef: {…}, elDef: {…}, elView: {…}}

Here is my forms.component.ts file:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormService } from './forms.service';
import { form } from './form-interface';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-forms',
  templateUrl: './forms.component.html',
  styleUrls: ['./forms.component.css']
})


export class FormsComponent implements OnInit {

  formsUrl = "https://jsonplaceholder.typicode.com/posts";
  id: any;
  form: form = {
    id: 0,
    userId: 0,
    title: '',
    body: ''
  };

  constructor(private formService: FormService ,private route: ActivatedRoute,
    private router: Router, private http: HttpClient) { }

  ngOnInit() {
    this.id=this.route.snapshot.params['id'];

    this.formService.getForms(this.id).subscribe(
      (forms: any) => {
        this.form = forms[0];
        console.log(this.form);
      }
    );

  }

  deleteForm() {
    this.http.delete(this.formsUrl + "/" + this.form.id)
    .subscribe(
      data  => {
      console.log("DELETE Request is successful ", data);
      },
      error  => {
      console.log("Error", error);
      }
    );
  }

}

here is my forms.service.ts file:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { form } from './form-interface';



@Injectable({
    providedIn: 'root'
}) 

export class FormService {

formsUrl = "https://jsonplaceholder.typicode.com/posts";
form: form = {
    id: 0,
    userId: 0,
    title: '',
    body: ''
  };


    constructor(private http: HttpClient) { }

    getForms(id) {
        return this.http.get('https://jsonplaceholder.typicode.com/posts'
        + "?id=" + id)
      }

      editForm() {
        fetch(this.formsUrl + "/" + this.form.id, {
          method: 'PUT',
          body: JSON.stringify(this.form),
          headers: {
            "Content-type": "application/json; charset=UTF-8"
          }
        })
        .then(response => response.json())
        .then(json => console.log(json));
      }


}

And here is my HTML file:

<div class="forms container">
  <form #postForm="ngForm">
      <div class="form-group">
          <label for="title">Title</label>
          <input [(ngModel)]="form.title"
          name="title"  
          id="title" 
          type="text" 
          class="form-control"
          >
      </div>
      <div class="form-group">
        <label for="body">Body</label>
        <textarea [(ngModel)]="form.body" 
        name= "body" 
        id="body" 
        cols="30" 
        rows="10" 
        class="form-control"
        ></textarea>
      </div>
      <button class="btn btn-success" (click) = editForm()>Save</button>
      <button class="btn btn-danger pull-right" (click) = deleteForm()>Delete</button>
  </form>
</div>

You cannot call editForm() in the template as it is not existing in your component. If you want to call that function from the service, use formService.editForm() instead

But in that case, you need to make formService public, so use public formService: FormService instead of private formService: FormService .

You can also clone that function in the component so you don't need to change the template and make the service public, as public editForm = formService.editForm

or

editForm() {
     return this.formService.editForm();
}

seems that parse error. try fix error in html:

put (click) = "editForm()" and (click) = "deleteForm()"

<div class="forms container">
  <form #postForm="ngForm">
      <div class="form-group">
          <label for="title">Title</label>
          <input [(ngModel)]="form.title"
          name="title"  
          id="title" 
          type="text" 
          class="form-control"
          >
      </div>
      <div class="form-group">
        <label for="body">Body</label>
        <textarea [(ngModel)]="form.body" 
        name= "body" 
        id="body" 
        cols="30" 
        rows="10" 
        class="form-control"
        ></textarea>
      </div>
      <button class="btn btn-success" (click) = "editForm()">Save</button>
      <button class="btn btn-danger pull-right" (click) = "deleteForm()">Delete</button>
  </form>
</div>

If you want to keep it clean and tidy you can do something like this:

export class FormsComponent implements OnInit {
  form = this.formService.form;

  constructor(private formService: FormService, private route: ActivatedRoute,
    private router: Router) { }

  ngOnInit() {
    this.id = this.route.snapshot.params['id'];

    this.formService.loadFormsById(this.id)
        .subscribe(([form]) => this.formService.updateForm(form));
  }

  saveForm() {
    this.formService.saveForm();
  }

  deleteForm() {
    this.formService.deleteForm();
  }

}

And Service:

export class FormService {

    formsUrl = "https://jsonplaceholder.typicode.com/posts";
    form: form = {
       id: 0,
       userId: 0,
       title: '',
       body: ''
    };


    constructor(private http: HttpClient) { }

    loadFormsById(id) {
       // load your form here
    }

    updateForm(form) {
       // update your form here
    }

    saveForm() {
       // save your form here
    }

    deleteForm() {
       // delete your form here
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM