2

I would like to initialize my select with a variable called : listClient, which exists in component : project.component.ts. I'm using ng2-select in angular5.

This is the file project.component.ts:

import {Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {ProjetService} from '../../../../../service/projet.service';
import {Projet} from '../../Models/Projet';
import { ModalDirective } from 'ngx-bootstrap/modal';
import 'rxjs/add/operator/map';
import {ClientService} from '../../../../../service/client.service';

@Component({
  selector: 'app-projects',
  templateUrl: './projects.component.html',
  styleUrls: ['./projects.component.scss']
})
export class ProjectsComponent implements OnInit {

listClients:any;

constructor(private router:Router,
              private projetSevice:ProjetService,
              private clientServ:ClientService,
              private route: ActivatedRoute) { }

 ngOnInit() {
       this.doSearch();
       this.clientList(); // to initialize the variable listClient i want to 
                             show in ng2-select
  }

clientList(){
    this.clientServ.getListClients()
      .subscribe((data:any)=>{
        this.listClients=data;
      },err=>{
        console.log('this is error ');
      })
  }

public selected(value:any):void {
    console.log('Selected value is: ', value);
  }

  public removed(value:any):void {
    console.log('Removed value is: ', value);
  }

  public typed(value:any):void {
    console.log('New search input: ', value);
  }

  public refreshValue(value:any):void {
    this.value = value;
  }



}

This is project.component.html:

<div class="form-group row">
      <label class="col-sm-5 col-form-label">To select a client : </label>
      <div class="col-sm-6">

        <ng-select [allowClear]="true"
                   [items]=""
                   (data)="refreshValue($event)"
                   (selected)="selected($event)"
                   (removed)="removed($event)"
                   (typed)="typed($event)"
                   placeholder="select a client"

        >
        </ng-select>


      </div>
    </div>

The variable listClient is like:

{
id : 1
firstname : "jack"
lastname  : "alterd"
....

}

I want to show only the firstname with lastname and then send the selected id to project.component.ts

I can't find any complete example on how to do that, any idea?

Pete
  • 769
  • 7
  • 20
dEs12ZER
  • 788
  • 4
  • 24
  • 51

1 Answers1

3

I believe you are using this ng2-select: https://valor-software.com/ng2-select/.

The documentation states that the items collection must have an id property and a text property. From doc:

items - (Array) - Array of items from which to select. Should be an array of objects with id and text properties.

Since your listClient does not have those properties, I would recommend writing a getter in Typescript to return a mapped list that does.

Set the items property:

<div class="form-group row">
    <label class="col-sm-5 col-form-label">To select a client : </label>
    <div class="col-sm-6">

    <ng-select *ngIf="_listClients"
               [allowClear]="true"
               [items]="listClient"
               (data)="refreshValue($event)"
               (selected)="selected($event)"
               (removed)="removed($event)"
               (typed)="typed($event)"
               placeholder="select a client">
    </ng-select>


  </div>
</div>

Map the values using a get in Typescript:

import {Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {ProjetService} from '../../../../../service/projet.service';
import {Projet} from '../../Models/Projet';
import { ModalDirective } from 'ngx-bootstrap/modal';
import 'rxjs/add/operator/map';
import {ClientService} from '../../../../../service/client.service';

@Component({
  selector: 'app-projects',
  templateUrl: './projects.component.html',
  styleUrls: ['./projects.component.scss']
})
export class ProjectsComponent implements OnInit {

//create private instance
_listClients:any;

constructor(private router:Router,
              private projetSevice:ProjetService,
              private clientServ:ClientService,
              private route: ActivatedRoute) { }

 ngOnInit() {
       this.doSearch();
       this.clientList(); // to initialize the variable listClient i want to 
                          // show in ng2-select
  }
  //list client getter
  get listClient() {
    return this._listClients ? this._listClients.map(item => {
      return { id: item.id, text: (item.lastName + ', ' + item.firstName)}
    }) : [];
  }

clientList(){
    this.clientServ.getListClients()
      .subscribe((data:any)=>{
        //initialize the private instance
        this._listClients=data;
      },err=>{
        console.log('this is error ');
      })
  }

public selected(value:any):void {
    console.log('Selected value is: ', value);
  }

  public removed(value:any):void {
    console.log('Removed value is: ', value);
  }

  public typed(value:any):void {
    console.log('New search input: ', value);
  }

  public refreshValue(value:any):void {
    this.value = value;
  }



}
Pete
  • 769
  • 7
  • 20
  • thank you for your help , before i'll try this , can you please tell me where are you using the getter listClient() ? – dEs12ZER May 12 '18 at 18:53
  • Yes, in the template when we set the [items] property. By saying listClient, we are using the get method which is defined as get listClient(). – Pete May 12 '18 at 18:55
  • Ah okey this is clear now , i'll try this right now and tell you the result – dEs12ZER May 12 '18 at 18:55
  • i think there is a problem with map , i get this error : ERROR TypeError: Cannot read property 'map' of undefined at ProjectsComponent.get [as listClient] – dEs12ZER May 12 '18 at 19:06
  • This sounds more like the data isn't available to the template at the time listClient is accessed. I edited my answer to include an *ngIf="listClient" so the element will not be rendered until data is available. – Pete May 12 '18 at 19:08
  • Added one more edit to make the _listClients public and use that to determine if data is available. – Pete May 12 '18 at 19:12
  • I also added a check to see if _listClients is null: return this._listClients ? this._listClients.map(item => { return { id: item.id, text: (item.lastName + ', ' + item.firstName)} }) : []; – Pete May 12 '18 at 19:20
  • for now there is no error , but the ng2-select is emty , what do you think about that ? – dEs12ZER May 12 '18 at 19:26
  • I have created a small example that will load the options after 3 seconds here: https://stackblitz.com/edit/angular-ejtkkd – Pete May 12 '18 at 19:45
  • yeah i see , it's weired i did the same as in this exemple in my project but the ng select is always empty , i did a console.log(this._listClients) in clientList() and everything is well (means no problem with backend ) , – dEs12ZER May 12 '18 at 20:12
  • can you please tell me how can i test the result of get listClient() ? – dEs12ZER May 12 '18 at 20:13
  • Can you place it in an angular expression in your template somewhere on the page?
    {{item.text}}
    – Pete May 12 '18 at 20:17
  • back again , the
    shows exactly the first name and lastename without any problem , i think i have a problem in ng2-select itself
    – dEs12ZER May 12 '18 at 20:27
  • Can you remove most of the events? Basically try to get it as minimal as possible similar to this: https://stackblitz.com/edit/angular-ejtkkd – Pete May 12 '18 at 21:07
  • so sad to tell you that , i have always the same problem , this is really weired – dEs12ZER May 12 '18 at 21:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170924/discussion-between-peter-and-des12zer). – Pete May 12 '18 at 21:35