ngx-mat-select-search icon indicating copy to clipboard operation
ngx-mat-select-search copied to clipboard

[QUESTION] How to set a default value using server look up

Open boscharnau opened this issue 3 years ago • 8 comments

Hi,

I want to set the initial value on the input. I have tried multiple things, but no matter what I do, I can't set the initial value to the input.

Let me explain my application. I have an Object Project, which has assigned a Customer. So, if I am editing an existing Project the input has to show it's customer name.

I am not able to setValue() to the input if we got customerIdProject. How I can achieve that? Input it should show the name of its customer assigned. image

If I create a new project, the input hasn't any initial value.

That's my code:

 <mat-form-field>
   <mat-select [formControl]="customerCtrl" placeholder="Customer" #singleSelect>
     <mat-option>
       <ngx-mat-select-search [formControl]="customerFilterCtrl" type='text' placeholderLabel='Search a customer'
         noEntriesFoundLabel="No customer found">
       </ngx-mat-select-search>
     </mat-option>
     <mat-option *ngFor=" let customer of filteredCustomers" [value]="customer">
       {{customer?.name}}
     </mat-option>
   </mat-select>
 </mat-form-field>

I want to simulate a lazy loading, and the fetch has to be done on the server, not on the front because I can have thousonds of customers and the performance will be so horrible.

export class CustomerInputComponent implements OnInit {
  public customerCtrl: FormControl = new FormControl();
  public customerFilterCtrl: FormControl = new FormControl();
  public filteredCustomers: ReplaySubject<any[]> = new ReplaySubject<any[]>(1);
  protected _onDestroy = new Subject<void>();
  customers = [];
  @Input() formProject: FormGroup;
  @Input() customerIdProject: string;
  @ViewChild("singleSelect") singleSelect: MatSelect;


  constructor(
    private route: ActivatedRoute,
    private customerService: CustomerService
  ) {}

  ngOnInit() {
    if (this.customerIdProject) {
        this.customerService.findOne(this.customerIdProject).subscribe((result) => {
        this.customers.push(result.data);
        this.customerCtrl.setValue(this.customers[0]); // it should be passed an array with an index selected?
      });
    }
	  
    this.customerFilterCtrl.valueChanges
      .pipe(
        filter((search) => !!search),
        takeUntil(this._onDestroy),
        debounceTime(200)
      )
      .subscribe(() => {//filtering by input typed. that is working
        this.customerService
          .getAll(null, this.customerFilterCtrl.value) 
          .subscribe((result) => {
            this.filteredCustomers = result.docs;
          });
      });
  }
  ngOnDestroy() {
      this._onDestroy.next();
      this._onDestroy.complete();
    }
}

Example if filter is 'john': It will return all the customers that each name contains the word 'john'.

this.customerService
          .getAll(null, this.customerFilterCtrl.value)

image

Thanks.

boscharnau avatar Apr 08 '21 08:04 boscharnau

Does this help you? https://github.com/bithost-gmbh/ngx-mat-select-search/issues/299#issuecomment-762843609

macjohnny avatar Apr 08 '21 11:04 macjohnny

No! It didn't help me.

boscharnau avatar Apr 12 '21 09:04 boscharnau

Add an invisible option for the selected value:

<mat-form-field>
   <mat-select [formControl]="customerCtrl" placeholder="Customer" #singleSelect>
     <mat-option>
       <ngx-mat-select-search [formControl]="customerFilterCtrl" type='text' placeholderLabel='Search a customer'
         noEntriesFoundLabel="No customer found">
       </ngx-mat-select-search>
     </mat-option>

     <mat-option [value]="customerCtrl.value" style="display: none">
       {{ customerCtrl.value?.name }}
     </mat-option>

     <mat-option *ngFor=" let customer of filteredCustomers" [value]="customer">
       {{customer?.name}}
     </mat-option>
   </mat-select>
 </mat-form-field>

Or push value to filteredCustomers:

if (this.customerIdProject) {
   this.customerService.findOne(this.customerIdProject).subscribe((result) => {
      const subscription = this.filteredCustomers.subscribe(() => this.customerCtrl.setValue(result.data));
      this.filteredCustomers.next([result.data]);
      subscription.unsubscribe();
   });
}

Knoxvillekm avatar Apr 20 '21 23:04 Knoxvillekm

@boscharnau is this resolved?

macjohnny avatar Aug 06 '21 07:08 macjohnny

@Knoxvillekm @macjohnny Another issue when using multi-select, when you deselect the last one from filtered results, it will deselect all, included previous selected values stackblitz yeqIVVnXAd-output

adding the invisible option solves it, but causes a different issue with ctrl+a. instead of deselecting all (after selecting all) it selects all again.

MoishyS avatar Oct 06 '21 20:10 MoishyS

we can solve the issue partially, by only showing options that are not in the filtered results stackblitz

this.hiddenOptions = this.filteredServerSideBanks.pipe(
      map(
        (values) =>
          this.bankServerSideCtrl.value?.filter(
            (a) => !values.find((b) => a.id == b.id)
          ) ?? []
      )
    );

it's still an issue when you deselect all (ctrl+a), it will also deselect the options that aren't included in the filtered results.

MoishyS avatar Oct 07 '21 00:10 MoishyS

ok, was able to solve it, by only showing the options if search ctrl is empty stackblitz

<ng-container *ngIf="!bankServerSideFilteringCtrl.value">
   <mat-option *ngFor="let bank of bankServerSideCtrl.value"
       [value]="bank" style="display: none">
     {{ bank.name }}
  </mat-option>
</ng-container>

also need to remove filter((search) => !!search) as we won't hide the options when the select is visible, and will then have the issues with ctrl+a.

my question is, if this is the right way to fix, or do we have a better solution?

MoishyS avatar Oct 07 '21 03:10 MoishyS

@MoishyS thanks for reporting an issue. I moved the discussion to https://github.com/bithost-gmbh/ngx-mat-select-search/issues/339

macjohnny avatar Oct 07 '21 06:10 macjohnny