Interface dependency injection in Typescript - Angular 6

Asked

Viewed 1,608 times

0

I am doing the front end of a project using Angular 6, but I am beginner in both Angular and Typescript and I am trying to use the interfaces of Typescript as in Java, injecting them to use the methods and tals, the problem is the following:

*I have an interface with the signature of the methods;

*I have a class q implements this interface and has the methods;

*I have a component q calls the interface on Contructor thus private myInterface: MyInterface and, at least in Java what I would do is make this attribute receive a new object from the class q implements this interface (this.myInterface = new ObjetoQueImplementa();) and could use their methods normally, but in Typescript is different, and I even saw articles and some examples that I found there with a certain injection of dependency as in Java but none of them came to help me, I will leave my code here I hope someone can help me here.

Interface:

import {Agenda} from "../model/agenda";
import {Observable} from "rxjs/index";

export interface AgendaCommandRepository {

  insert(agenda: Agenda): Observable<Agenda>;

  update(agenda: Agenda): Observable<Agenda>;

  deleteAgenda(id: number): Observable<number>;
}

Class implementing the interface:

import { Injectable } from '@angular/core';
import { AgendaService } from '../service/agenda-command.service';
import { AgendaCommandValidator } from '../validator/agenda-command-
validator';
import { Agenda } from '../../model/agenda';
import { Observable } from 'rxjs/index';

@Injectable({
  providedIn: 'root'
})
export class AgendaCommandRepositoryImpl implements AgendaCommandRepository {

  constructor(private service: AgendaService, private validator: 
AgendaCommandValidator) { }

  insert(agenda: Agenda): Observable<Agenda> {

    if (this.validator.validaInsert(agenda)) {
      return this.service.insert(agenda);
    }

    return null;
  }

  update(agenda: Agenda): Observable<Agenda> {

    if (this.validator.validaUpdate(agenda)) {
      return this.service.update(agenda);
    }

    return null;
  }

  deleteAgenda(id: number): Observable<number> {

    if (this.validator.validaDelete(id)) {
      return this.service.deleteAgenda(id);
    }

    return null;
  }
}

Component that injects the interface to call its methods and execute the code of the class q implements the interface:

import {Component, Inject, OnInit} from '@angular/core';
import { AgendaCommandRepositoryImpl } from "../../repository/agenda-
command-repository-impl";
import { Agenda } from "../../../model/agenda";
import { AgendaQueryRepository } from "../../../query/repository/agenda-
query-repository";
import { ActivatedRoute } from '@angular/router';
import { AgendaCommandRepository } from "../../agenda-command-repository";

@Component({
  selector: 'app-agenda',
  templateUrl: './agenda-command.component.html',
  styleUrls: ['./agenda-command.component.css']
})
export class AgendaCommandComponent implements OnInit {

  agenda: Agenda;
  id: number;
  titulo: string; // para teste

  constructor(private repository: AgendaCommandRepository, private 
queryRepository: AgendaQueryRepository, private route: ActivatedRoute) {}

  ngOnInit() {
    this.id = +this.route.snapshot.paramMap.get('id');

    if (this.id) {
      this.queryRepository.findById(this.id).subscribe(agenda => this.agenda 
= agenda);
      this.titulo = "Edição";

    } else {
      this.agenda = new Agenda();
      this.titulo = "Cadastro";
    }
  }

  salvar() {

    if (this.id) {
      this.repository.update(this.agenda).subscribe();

    } else {
      this.repository.insert(this.agenda).subscribe();
    }
  }

}
  • Your class AgendaCommandRepositoryImpl is not implementing AgendaCommandRepository, only has methods with the same name, missing the implements. When defining in the constructor which type is AgendaCommandRepository it will try to use the interface as value which will not work, you must directly pass the implementation AgendaCommandRepositoryImpl

  • @Guilhermecostamilam I’m sorry I copied wrong, the idea was to have the implements la, nn preucupe that I have already edited and fixed my mistake, but you have some idea how to solve this my problem?

  • Or you pass AgendaCommandRepositoryImpl in the constructor or private and in an instance the class this.repository = new AgendaCommandRepositoryImpl();

  • @Guilhermecostamilam pseh I tried this second option and it did not work, it gives an error saying that the this.repository expects 2 arguments and this getting 0, in my conception was to work but as nn understand mto of typescript my conception nn worth nothing, has some other idea?

  • Yes, this error occurs because the class AgendaCommandRepositoryImpl need to receive two parameters in your constructor, you need to take them when instantiating, when you create a direct instance in the constructor arguments the TS makes it automatic for you

  • @Guilhermecostamilam I think I understand what you mean, but does nn have an easier/more practical way of doing this? is that it seems to me that way "gambiarrento", it gets a code very ugly, like, the code would look like this this.repository = new AgendaCommandRepositoryImpl(new AgendaService(new HttpClient()), new AgendaCommandValidator()); There’s got to be some way to do it Without getting all twisted up...

  • Yes pass in constructor parameter the class that implements

  • @Guilhermecostamilam type like this constructor(private repository: AgendaCommandRepository, private repositoryImpl: AgendaCommandRepositoryImpl) { };?

  • pq if that’s the way it is, nn I want to have it instantiated or I would use its object msmo and nn would need the interface, I found a way to do exactly what I want and it works but I took from an example of Angular 4 I think and tbm this way that I found is more laborious and nn know if it’s worth it, look here dps to see this article sera q vc nn knows a way to make the result of this article without that gambiarra and all work?

Show 4 more comments

1 answer

0


With the help of @Guilhermecostamilam I found the answer, nn looks so beautiful but can use, ta ai the code:

Interface:

import {Agenda} from "../model/agenda";
import {Observable} from "rxjs/index";

export interface AgendaCommandRepository {

  insert(agenda: Agenda): Observable<Agenda>;

  update(agenda: Agenda): Observable<Agenda>;

  deleteAgenda(id: number): Observable<number>;
}

Class implementing the interface:

import { Injectable } from '@angular/core';
import { AgendaService } from '../service/agenda-command.service';
import { AgendaCommandValidator } from '../validator/agenda-command-validator';
import { Agenda } from '../../model/agenda';
import { Observable } from 'rxjs/index';

@Injectable({
  providedIn: 'root'
})
export class AgendaCommandRepositoryImpl implements AgendaCommandRepository {

  private service: AgendaService;
  private validator: AgendaCommandValidator;

  constructor(serviceImpl: AgendaServiceImpl, validatorImpl: AgendaCommandValidatorImpl) {
      this.service = serviceImpl;
      this.validator = validatorImpl;
  }

  insert(agenda: Agenda): Observable<Agenda> {

    if (this.validator.validaInsert(agenda)) {
      return this.service.insert(agenda);
    }

    return null;
  }

  update(agenda: Agenda): Observable<Agenda> {

    if (this.validator.validaUpdate(agenda)) {
      return this.service.update(agenda);
    }

    return null;
  }

  deleteAgenda(id: number): Observable<number> {

    if (this.validator.validaDelete(id)) {
      return this.service.deleteAgenda(id);
    }

    return null;
  }
}

Component:

import {Component, Inject, OnInit} from '@angular/core';
import { AgendaCommandRepositoryImpl } from "../../repository/agenda-command-repository-impl";
import { Agenda } from "../../../model/agenda";
import { AgendaQueryRepository } from "../../../query/repository/agenda-query-repository";
import { ActivatedRoute } from '@angular/router';
import { AgendaCommandRepository } from "../../agenda-command-repository";

@Component({
  selector: 'app-agenda',
  templateUrl: './agenda-command.component.html',
  styleUrls: ['./agenda-command.component.css']
})
export class AgendaCommandComponent implements OnInit {

  agenda: Agenda;
  id: number;
  titulo: string; // para teste
  private repository: AgendaCommandRepository;
  private queryRepository: AgendaQueryRepository;

  constructor(repositoryImpl: AgendaCommandRepositoryImpl, queryRepositoryImpl: AgendaQueryRepositoryImpl, private route: ActivatedRoute) {
  this.repository = repositoryImpl;
  this.queryRepository = queryRepositoryImpl;
  }

  ngOnInit() {
    this.id = +this.route.snapshot.paramMap.get('id');

    if (this.id) {
      this.queryRepository.findById(this.id).subscribe(agenda => this.agenda = agenda);
      this.titulo = "Edição";

    } else {
      this.agenda = new Agenda();
      this.titulo = "Cadastro";
    }
  }

  salvar() {

    if (this.id) {
      this.repository.update(this.agenda).subscribe();

    } else {
      this.repository.insert(this.agenda).subscribe();
    }
  }

}

Since Angular 6 already makes the class injection for me I just had to make Angular inject Impl(q is the code) and make the interface receive Impl, this vlw flw!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.