1

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.

6
  • What is error? If it's typescript, you might not be passing in a object with the wrong types so it will pass in nothing thus failing. How are you building your modal(ng2-ui-bootstrap)? I have some modal examples that were generated on the fly like what your doing. It was tricking passing in the data with the library if you dynamically generated the modal components. Commented Dec 15, 2016 at 19:25
  • What happens is: Listing sales, in the field customer, I use this minicustomer thing, passing the customer id via directive, like: Commented Dec 15, 2016 at 19:28
  • add some code to your question. You should convert that directive to a component if you want it to manipulate data. Commented Dec 15, 2016 at 19:29
  • What happens is: Listing sales, in the field customer, I use this minicustomer thing, passing the customer id via directive, like: <customermini [customerid] = "sale.customerid"></customermini> then in the customermini template, there are interpolation tags. The thing is, I don't want to load customer data for each sale. I wanted that the data for the modal would only be read whenever I click the button. The error is that the customer object in th Commented Dec 15, 2016 at 19:31
  • remove Injectable from customermini....it's not a service/singleton Commented Dec 15, 2016 at 19:42

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

5 Comments

The thing is, the button that activates the modal is in the customermini template, using this, the button simply doesn't render.
add the open function to your customermini component and put my template code in the customermini template file. The best, longer way is to have the open function on the parent and the child component customermini trigger it via @Outputs.
@user2960560 Check my improved answer;
Yeah, trying to wrap my mind around it... some stuff are hard yet to understand. I'm a newbie on Angular 2 still. But I'm trying to understand and put your suggestion onto it! Thank you!
Basically, any child component can emit an event to activate methods/functions on the parent component via @Outputs. The parent component revieves this as an $event which is the data you passed from the child component. Then open method takes that data on the parent and creates a modal out of a component(customermini modal). Keep in Mind!!!! the child component and modal component are separate components in my 2nd, more detailed example.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.