I would like to use a service in my class (model)
Use Service in my Class
movie-list.component.ts
import { Component, OnInit } from '@angular/core';
import {Movie} from "../../models/movie";
import {MovieService} from "../../services/movie.service";
@Component({
selector: 'movie-list',
templateUrl: './movie-list.component.html',
})
export class MovieListComponent implements OnInit {
public movies = [];
public movie: Movie;
constructor(private movieService: MovieService) {
this.movie = new Movie();
}
ngOnInit() {
console.log(this.movie.getMovies());
this.movies = movie.getMovies();
}
}
movie-list.component.html
<div *ngFor="let movie of movies">
{{ movie.title }}
<div *ngFor="let actor of movie.actors">
{{ actor.name }} - {{ actor.getOscar() }}
</div>
</div>
movie.ts (movie model)
import { Actor } from "./actor";
export class Movie {
constructor(title: string = '', actors: any = []) {
this.title = title;
this.actors = [];
}
title: string = '';
actors: any = [];
movieService;
setModel(obj) {
Object.assign(this, obj);
}
addActor(actor) {
this.actors.push(actor);
}
build(data) {
let movie = new Movie(
data.title,
data.actors
);
movie.setModel({ actors: []});
data.actors.forEach((actor) => {
let new_actor = new Actor(
actor.firstname,
actor.lastname
);
movie.addActor(new_actor);
});
return movie;
}
getMovies() {
let movies: any[];
this.movieService.getMovies().subscribe(
data => {
data.map((result) => {
movies.push(this.build(result));
});
return movies;
},
error => {
console.error(error);
}
)
}
}
actor.ts (actor model)
export class Actor {
constructor(firstname: string, lastname: string) {
this.firstname = firstname;
this.lastname = lastname;
}
firstname: string;
lastname: string;
setModel(obj) {
Object.assign(this, obj);
}
getOscar() {
return '10 oscars';
};
}
movie.service.ts
import { Injectable } from '@angular/core';
import {Http} from "@angular/http";
import 'rxjs/add/operator/map';
@Injectable()
export class MovieService {
constructor(private http:Http) { }
getMovies() {
return this.http
.get('data/movies.json')
.map(res => res.json());
}
}
movies.json
[
{
"title": "title1",
"actors": [
{
"firstname": "firstname10",
"lastname": "lastname10"
},
{
"firstname": "firstname11",
"lastname": "lastname11"
}
]
},
{
"title": "title2",
"actors": [
{
"firstname": "firstname20",
"lastname": "lastname20"
},
{
"firstname": "firstname21",
"lastname": "lastname21"
}
]
}
]
I would like to "inject/use" my service in my Class to use this workflow:
I tried to use @inject in my Class but it doesn't work from this post How to inject Service into class(not component)
I would like to know the best practice to do this.
With this code, I have an error :

Modification
Added this in my component :
constructor(private movieService: MovieService) {
this.movie = new Movie();
this.movie.movieService = movieService; // add this line
}
I have an error on this line in my component :
ngOnInit() {
console.log(this.movie.getMovies());
this.movies = movie.getMovies(); // error Type 'void' is not assignable to type 'any[]'.
}
I would like to conserve the subscribe in the model to have a clean code in my component

SOLVED
movie-list.component.ts
import { Component, OnInit } from '@angular/core';
import { Movie } from "../../models/movie";
import { MovieService } from "../../services/movie.service";
@Component({
selector: 'movie-list',
templateUrl: './movie-list.component.html',
})
export class MovieListComponent implements OnInit {
public movie: Movie;
public movies = [];
constructor(private movieService: MovieService) {
this.movie = new Movie('', []);
this.movie.movieService = movieService;
}
ngOnInit() {
this.movies = this.movie.getMovies();
}
}
movie.ts
import { MovieService } from "../services/movie.service";
import { Actor } from "./actor";
export class Movie {
constructor(
private title: string = '',
private actors: any[] = [],
) { }
public movieService : MovieService;
setModel(obj) {
Object.assign(this, obj);
}
addActor(actor) {
this.actors.push(actor);
}
build(data) {
const movie = new Movie(
data.title,
data.actors,
);
movie.setModel({ actors: [] });
data.actors.forEach((actor) => {
const new_actor = new Actor(
actor.firstname,
actor.lastname
);
movie.addActor(new_actor);
});
return movie;
}
getMovies() {
let movies = [];
this.movieService.getMovies().subscribe(
data => {
data.map((result) => {
movies.push(this.build(result));
});
},
error => {
console.error(error);
}
);
return movies;
}
}
You should read this about Smart and Presentation (Dumb) components. This is by far the best practice there is, as the whole angular data management and detection changes revolves around it.
http://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/
Your error comes from the two parameters you set in the constructor, as these should be sent either by the @Input decorator or fetched from a service.
You don't do things like let foo = new MovieComponent(.., ...); so this can't work.
Read this from the official documentation. It will also help you for setting up the smart / dumb component structure :
https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding
EDIT : To make your service work, simply pass it as a dependency into your MovieComponent constructor like to :
constructor(
private movieService: MovieService
) {}
Do not forget to provide your MovieService in your (I expect) MovieModule or wherever the MovieComponent is declared (in the same module)
EDIT2 : Here are the code parts that worked for me. The model class would need to be reworked, with a method to send back the movies built asynchronously, but even then, I'd find that model not very useful. You are better off using only interfaces and a service. Also, this is obviously not a smart/dumb component interaction, so some upgrades will be needed to achieve what you want.
MovieListComponent
export class MovieListComponent implements OnInit {
public movies = [];
public movie: Movie;
constructor(private movieService: MovieService) {
this.movie = new Movie('', []);
}
ngOnInit() {
this.movie.movieService = this.movieService;
this.movie.getMovies().subscribe(
data => {
data.map((result) => {
this.movies.push(this.movie.build(result));
});
}
);
}
}
Movie (model)
export class Movie {
movies: any[];
movieService: MovieService
constructor(
private title: string = '',
private actors: any[] = [],
) { }
setModel(obj) {
Object.assign(this, obj);
}
addActor(actor) {
this.actors.push(actor);
}
build(data) {
const movie = new Movie(
data.title,
data.actors,
);
movie.setModel({ actors: [] });
data.actors.forEach((actor) => {
const new_actor = new Actor(
actor.firstname,
actor.lastname
);
movie.addActor(new_actor);
});
return movie;
}
getMovies() {
return this.movieService.getMovies();
}
}
Module
@NgModule({
imports: [
HttpModule,
CommonModule
],
declarations: [
MovieListComponent
],
providers: [
MovieService
]
})
export class MainModule { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With