user2960560
user2960560

Reputation: 31

Angular 2 component inside component

Ok, Angular 2 is seems very cool as of now, but I'm still getting some trouble with it. The thing is, I want "mini view components", meaning a small view of some item(a customer for example) as a button or a link. Example: A sales listing(this part I mnanaged to figure out), it contains a field which is the customer, instead of only showing the customer id in there, I wanted it to be a button that when clicked a modal window(bootstrap modal) would show with the details of the customer. This same behaviour also to suppliers, products and so on. I've tried to make a "customermini" component. I pass the customer code as a directive and the button fires "getCustomer", which fires a service method and gets the customer. This is all going "mediocre". The thing is, that this "minicustomer" component, has its interpolation with the object got in the "getCustomer" method. But whenever the interpolation "fires" I get an error. So the question is: What is the best approach to this situation? I want this "mini" components to be available everywhere accross the application, since there are many "thingies" that in the listings will be only an id, but I want them to be "viewable". And than you in advance.

Edit: Adding some code:

import {Component} from "angular2/core";
import {ClienteService} from "./clientes.service";
import {Cliente} from "./cliente.model"; 
import {DateString} from './dateString.pipe';
import {CustomerMiniComponent} from "./customer.mini.component";

@Component({
selector: 'saleslist',
templateUrl: 'app/sales.template.html',
directives: [CustomerMiniComponent],
pipes: [DateString]
})
export class SalesListComponent{
clientes: Cliente[];
constructor(private clienteService: ClienteService ){};
lerClientes(){
    this.clienteService.getClientes().subscribe(clientes => this.clientes = clientes,
    err => {
        console.log(err);
    });

}
  ngOnInit(){
        this.lerClientes(); //this is where I get the sales data, don't mind the names, its only a sandbox project, so...
}
}

The service:

import {Injectable} from 'angular2/core';
import { Http, Response, Headers, RequestOptions } from 'angular2/http';
import {Observable} from "rxjs/Rx";
import {Cliente} from "./cliente.model";

@Injectable()
export class ClienteService {
private url = "http://localhost:8080/api/clientes";

constructor(private http: Http){

}
getCliente (codigo) :Observable<Cliente[]>
{
    return this.http.get(this.url + "/" + codigo)
        .map((res:Response) => res.json())
        .catch((error:any) => Observable.throw(error.json().error || 'Server error')); ;
    // var tudo;
    // return this.http.get(this.url + "/" + codigo)
    //     .map((res:Response) =>{tudo = res.json(); var cli = new Cliente; cli=tudo; console.log(cli);})
    //     .catch((error:any) => Observable.throw(error.json().error || 'Server error'));

}

getClientes () :Observable<Cliente[]>
{
    return this.http.get(this.url)
        .map((res:Response) => res.json())
        .catch((error:any) => Observable.throw(error.json().error || 'Server error')); ;
}

}

The Customermini:

import {Component, Input, Injectable} from "angular2/core";
import {Cliente} from "./cliente.model";
import {DateString} from './dateString.pipe';
import {ClienteService} from "./clientes.service";


@Injectable()
@Component({
selector: 'customermini',
templateUrl: 'app/customer.mini.template.html',
pipes: [DateString]

})

export class CustomerMiniComponent{
@Input('codigo') clicli: string;

ClienteGot: Cliente[];
Cliente: Cliente;
    constructor(private clienteService: ClienteService){};

public lerCliente(){
    this.clienteService.getCliente(this.clicli).subscribe(cli => this.ClienteGot = cli);


    if (this.ClienteGot != undefined)
    {
        this.Cliente = this.ClienteGot[0];
        console.log(this.Cliente);
    }

}
  ngOnInit(){
      //this.lerCliente();
}
}

And in the customermini template html, there are the interpolation tags for the object "Cliente" which is the customer.

Upvotes: 1

Views: 1322

Answers (1)

deek
deek

Reputation: 1095

Easy answer would be to hide customermini based on status. When you click, it will show.

<button (click)="!show-modal-component"> </button>

<customermini *ngIf="show-modal-component === true" [customerid]="sale.customerid"></customermini>

If it's a modal component that must be dynamically generated/launched, then you will need to open the modal in the parent or child component and pass in data to the function/method that lanuches(ng2-ui-bootstrap) and add those modal components to "entryComponents:[]" in app modules while having this inside the html somewhere. Your Modal will not be created or load data until button is clicked. Library for my modal is part of "ng2-ui-bootstrap" aka Angular 2 bootstrap.

  <template ngbModalContainer></template>


<button (click)="open(content/data to be passed to modal on click event, will launch your customermini modal)"> </button>

in my component:

import {customermini} from "./location of customermini component ts file"

  /**
   * [open open my modal for making events or other stuff!]
   * @param {any} modalContent [any modal component]
   */


  open(modalContent: any): void {

         let modal = this.modalService.open(customermini);
// Important! you can now pass in data to customermini. Will also launch //customermini
       modal.componentInstance.customerInfo = modalContent;

      }

Best practice is having child components trigger modal opening via outputs:

In child Component(not customermini btw, that's your modal I assume):

@Output() openModal: EventEmitter<any> = new EventEmitter();

      openModalNow(componentModaldata: any): void {
        this.openModal.emit(componentModaldata);
      }

Child Component's HTML:

<button (click)="openModalNow(data for modal)" </button>

In parent Component:

open(modalContent: any): void {

             let modal = this.modalService.open(customermini);
    // Important! you can now pass in data to customermini. Will also launch //customermini
           modal.componentInstance.customerid = modalContent.customerid;

          }

In parent Component's HTML

<childComponent (openModal)='open($event)'> </childComponent>

Upvotes: 1

Related Questions