OOP: ¿Cómo pasar valores del método de una clase al método de otra clase en TypeScript?
Soy nuevo en la programación orientada a objetos y estoy suponiendo que esto debería ser un concepto fácil para los programadores OO experimentados, pero ciertamente estoy teniendo dificultades con él.
En mi aplicación Angular2 tengo una clase HttpService como se muestra a continuación:
http.service.ts
@Injectable()
export class HttpService {
constructor(private http: Http) { }
addLeaf(parentId, label, name){
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:8000/addleaf/',
{'parentId':parentId,'label':label, 'name':name},
{ headers: headers })
.map(res => res).subscribe();
}
Intento llamar a este método desde otra clase de la siguiente manera:
leaf.ts
import { HttpService } from './http.service';
export class Leaf{
name: string;
...
http: Http; // very unsure about these two lines
private httpService: HttpService = new HttpService(this.http)
constructor(input){
this.name = input.name;
...
add(){
//what should go here?
this.httpservice.addLeaf(this.id, this.label, this.name);
//error -> cannot read property 'post' of undefined
}
Leyendo esto, intenté crear una instancia de la clase HttpService pero obtengo el error de que la función post no existe. Tampoco tuve suerte poniendo el httpService en el constructor.
Llamo al método en mi HTML así:
(click)="leaf.add()"
EDITAR: siguiendo la respuesta de @peeskillet, modifiqué leaf.ts y añadí leaf.component.ts como se muestra:
leaf.ts
export class Leaf{
name: string;
...
constructor(input){
this.name = input.name;
...
add(){
//what should go here?
}
}
leaf.component.ts
@Component({
providers: [HttpService],
})
export class LeafComponent {
leaf: Leaf;
constructor(private httpService: HttpService) {
this.httpService.addLeaf(this.leaf.id, this.leaf.type, this.leaf.name)
}
}
El servicio funciona bien si escribo cadenas predefinidas en lugar de los parámetros, pero todavía no estoy seguro de cómo puedo pasar los parámetros de la hoja clickeada a esto.
Respuesta #1
Con Angular, usamos inyección de dependencias e Inversión de Control. Esto significa que no creamos el servicio nosotros mismos, sino que dejamos que Angular lo cree. Luego simplemente pedimos el servicio, y Angular resolverá cualquier dependencia que tenga ese servicio. Tomemos como ejemplo
@Injectable()
class Service {
constructor(private http: Http) {}
}
Aquí, Service tiene una dependencia en Http. Http no es algo que podamos obtener de la nada. No podemos simplemente hacer
let service = new Service(new Http());
Http también depende de algunos otros servicios. Aquí es cómo se ve su constructor
class Http {
constructor(backend: ConnectionBackend, options: RequestOptions) {}
}
Podrías pensar que tal vez puedes simplemente instanciarlo con el ConnectionBackend y RequestOptions
new Http(new ConnectionBackend(), new RequestOptions())`
Pero tampoco puedes hacer esto, ya que ConnectionBackend también tiene dependencias requeridas. Es por esta razón que usamos la Inversión de Control. Simplemente añadimos el servicio a un contenedor, y cuando pedimos el servicio, Angular buscará el servicio, verá que requiere Http, y verá que Http requiere ConnectionBackend y RequestOptions, etc., y Angular creará todos los elementos, buscando en su registro todos esos elementos y juntándolos como Voltron. Luego nos dará el servicio, completamente poblado.
Entonces, para agregar nuestro servicio al contenedor, primero necesitamos agregar el decorador Injectable en el servicio
@Injectable()
class Service {
constructor(private http: Http) {}
}
Entonces necesitamos agregarlo a los @NgModule.providers
@NgModule({
imports: [ HttpModule ],
providers: [ Service ]
})
class AppModule {}
Ahora, cada vez que solicitemos Service, estará completamente poblado con el Http (que está en el HttpModule).
Cómo solicitamos el servicio es a través del constructor de otro servicio o componente (directiva, pipe, etc.)
@Component({
})
class MyComponent {
constructor(private service: Service) {}
}
Al ver el tipo Service como un argumento del constructor, Angular sabe buscar el Service en su contenedor, luego pasárnoslo. Esto es lo básico de la Inyección de Dependencias e Inversión de Control.
En tu caso de Leaf. Si se supone que es un servicio, entonces puedes hacer lo mismo
@Injectable()
class Leaf {
constructor(private service: Service) {}
}
@NgModule({
imports: [ HttpModule ],
providers: [ Leaf, Service ]
})
class AppModule {}
Si no quieres añadir Leaf como proveedor, no necesitas hacerlo. Simplemente haz
@Component({})
class MyComponent {
leaf: Leaf;
constructor(private service: Service) {
this.leaf = new Leaf(service);
}
}
