Setting a default value in ngx-mat-select-search

I am currently working on the edit page for my project. I am trying to set the default value as the data sent by the server, but it's not working as expected. Can someone help me figure out what I'm doing wrong?

Here is a link to my code on StackBlitz

.ts

  public manufacturerMultiFilterCtrl: FormControl = new FormControl();
  protected _onDestroy = new Subject<void>();
  public filteredManufacturers: ReplaySubject<any[]> = new ReplaySubject<any[]>(
    1
  );

  set data(data: any[]) {
    this.manuf = data;
    // load the initial list
    this.filteredManufacturers.next(this.data.slice());
  }

  constructor(private fb: FormBuilder) {}

  @ViewChild('multiSelect', { static: true }) multiSelect: MatSelect;

  ngOnInit() {
    //chosen data
    this.carDetail = {
      manufacturer: 'manuf',
      manufacturerId: 1,
    };
    this.updateEstimation = this.fb.group({
      manufacturer: [this.carDetail.manufacturer],
    });
    this.updateEstimation.controls['manufacturer'].setValue(
      this.carDetail.manufacturer
    );
    //all manufacturers
    this.manuf = [
      {
        manufacturerId: 1,
        name: 'manuf',
      },
      {
        manufacturerId: 2,
        name: 'manuf1',
      },
    ];
    this.filteredManufacturers.next(this.manuf);
  }
  ngAfterViewInit() {
    this.setInitialValue();
  }

  protected setInitialValue() {
    this.filteredManufacturers
      .pipe(take(1), takeUntil(this._onDestroy))
      .subscribe(() => {
        console.log(this.multiSelect);
        this.multiSelect.compareWith = (a: string, b: string) => a === b;
      });
  }

Answer №1

Check out this functional stackblitz example: https://stackblitz.com/edit/angular-13-starter-x-z434ak?file=src/app/app.component.ts

The main issues can be summarized as follows:

  1. Ensure that you are wrapping your form within a formGroup properly.
  2. Double-check that the compareWith function is correctly comparing the necessary fields.

I made a change where the manufacturer field now holds the entire object. Upon closer inspection, there seems to be a discrepancy between the objects being compared. This mismatch might be caused by variations in what you're assigning as your source data and how each item is represented internally.

https://i.sstatic.net/fPRZ6.png

  1. If you prefer to directly use the name for comparison, your compareWith function should resemble this:

    compareFunction(o1: any, o2: any) {
     console.log('o1 is: ', o1, o2);
     return o1.name == o2;
     }
    

Given that o1 represents your manufacturer object and o2 is just the string value of the manufacturer's name, it appears that the issue stems from differing object types with overlapping characteristics but not identical structures. It's crucial for both your data source and individual items to mirror each other.

Here's another stack blitz link demonstrating a straightforward example of using compareWith effectively: https://stackblitz.com/edit/angular-material-select-compare-with?embed=1&file=app/app.html

Edit: In case Stackblitz loads slowly or access is lost due to non-registration with Github during edits:

HTML:

<div class="details align-items-center d-flex" [formGroup]="updateEstimation">
  <mat-form-field appearance="fill" class="nusx">
    <mat-select formControlName="manufacturer" [compareWith]="compareFunction" #multiSelect>
      <mat-option>
        <ngx-mat-select-search
          formControlName="manufacturerMultiFilterCtrl"
          [placeholderLabel]="'search...'"
          [noEntriesFoundLabel]="'not found'" 
        >
        </ngx-mat-select-search>
      </mat-option>
      <mat-option
        *ngFor="let item of filteredManufacturers | async"
        [value]="item"
        >{{ item.name }}
      </mat-option>
    </mat-select>
  </mat-form-field>
</div>

TS:

import { Component, ViewChild, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { MatSelect } from '@angular/material/select';
import { ReplaySubject, Subject, take, takeUntil } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  manuf: any;
  carDetail: any;
  updateEstimation: FormGroup;
  protected _onDestroy = new Subject<void>();
  public filteredManufacturers: ReplaySubject<any[]> = new ReplaySubject<any[]>(
    1
  );

  set data(data: any[]) {
    this.manuf = data;
    // load the initial list
    this.filteredManufacturers.next(this.data.slice());
  }

  constructor(private fb: FormBuilder) {}

  @ViewChild('multiSelect', { static: true }) multiSelect: MatSelect;

  ngOnInit() {
    //chosen data
    this.carDetail = {
      carId: 3,
      registrationNumber: 'yyyyyyyy',
      manufacturer: 'manuf',
      manufacturerId: 1,
      carModel: 'carmod',
      carModelId: 1,
      year: 2021,
      vincode: 'yyyyyyyy',
    };

    console.log('overall data', this.filteredManufacturers);
    console.log('manufacturer oninit: ', this.carDetail.manufacturer);

    this.updateEstimation = this.fb.group({
      manufacturer: [this.carDetail],
      manufacturerMultiFilterCtrl: [this.carDetail.manufacturer],
    });

    //all manufacturers
    this.manuf = [
      {
        manufacturerId: 1,
        name: 'manuf',
        carModels: [
          {
            carModelId: 1,
            name: 'carmod',
          },
          {
            carModelId: 2,
            name: 'Carmod1',
          },
        ],
      },
      {
        manufacturerId: 2,
        name: 'manuf1',
        carModels: [
          {
            carModelId: 3,
            name: 'Carmod2',
          },
        ],
      },
    ];
    this.filteredManufacturers.next(this.manuf);
  }

  compareFunction(o1: any, o2: any) {
    console.log('o1 is: ', o1, o2);
    return o1.name == o2.manufacturer && o1.manufacturerId == o2.manufacturerId;
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Deciding between a Component, Resolver, or Guard for redirecting authentication in Angular: Which middleware option is the

Incorporating an external authentication system into my Angular application is currently my focus, and I am determined to follow the most effective approach. The authentication process functions in such a way that upon successful authentication from a des ...

Encountering a delay in receiving server data causing errors in Angular 2

Within the service class constructor, I make an http call to the server to fetch product category data and store it in the productCategories array. However, when I try to retrieve the productCategories array in the ngInit() function of my component, I enco ...

`Measuring Code Coverage in Jasmine Unit Tests`

Looking for assistance with unit testing my simple logger .ts file. Can someone help me fix the unit test? logging.service.ts import 'reflect-metadata'; // Required for tsyringe import { singleton } from 'tsyringe'; import { Category } ...

What is the best way to restrict a Generic type within a Typescript Function Interface?

Imagine having the following interface definitions: interface SomeInterface {a: string; b: number} interface SomeFunction<T> {(arg: T) :T} The usage of the function interface can be demonstrated like this: const myFun: SomeFunction<string> = a ...

Ways to postpone the initialization of an Angular application in order to display animations

Incorporating a loading animation into my Angular application has been a recent enhancement. The animation is positioned between the <app-root> HERE </app-root> tags. To ensure proper display and functionality of this animation, I am looking t ...

Interactive Modal Featuring Image Slider - Capture Names and Sequential Numbers

I successfully created a modal with an image slider using the bootstrap ngb-carousel. Is there a way to dynamically display the current image's name in the modal header and the numbering of images in the modal footer? For example, I want the modal h ...

Encountering TypeScript errors when trying to reference Angular2 within a Gulp setup

The issue at hand is: [11:16:06] TypeScript: 103 semantic errors [11:16:06] TypeScript: emit succeeded (with errors) I am currently using node v5.7.0 and npm 3.6.0 gulp -v: [11:26:58] Requiring external module babel-register [11:26:58] CLI version 3.9 ...

Is there a way for me to run code once the sidebar has finished its animation and is

If we consider a scenario where there is a function as illustrated below. The intention is to execute this.sidebarVisible = false; only after all the animations related to the code mentioned in sidebarClose() are completed. Any suggestions on how this can ...

Tips for ensuring that an AngularJS2 textbox accommodates the input text adequately

Is it possible to create 3 HTML text boxes with an initial width of 30px each? If someone types more text than what can fit in one box, I would like all three boxes to expand their widths to match the size of the largest text box. What is the most effect ...

Ways to stop dialog from disappearing in Reactjs

This code snippet demonstrates the implementation of a popup with buttons, where clicking the cancel button triggers a confirmation dialog. To make the popup disappear when clicked outside of it, the following event handling is employed: const popupRef = ...

Passing NextJS props as undefined can lead to unexpected behavior and

Struggling with dynamically passing props to output different photo galleries on various pages. One of the three props works fine, while the others are undefined and trigger a warning about an array with more than one element being passed to a title elemen ...

Exploring the Power of Angular 2+: Leveraging the canLoad Feature

I'm having trouble getting the canLoad function to work with routes. It seems like it's not functioning properly. I'm not sure why, maybe it's incompatible with canActivate or something, but I'm hoping someone here might know. Wh ...

Angular 4 project utilizing the Bootstrap framework

How can I utilize Bootstrap classes like nav-component and the data-toggle attribute in my Angular 4&5 project components within VS Code? After encountering issues with Bootstrap v3, I decided to upgrade to v4.1.7. Although I have linked the source file i ...

Angular asynchronous testing with Observable using karma

I am currently working on testing an asynchronous scenario. Here is a snippet of my component: ngOnInit(private service: MyService) { this.isLoading = true; this.service.getData().subscribe((data) => { this.data = data; this.isLoa ...

Each time I use console.log to display a user's radio button choice, the output is consistently lagging by one step

It seems that I am experiencing an issue where the console.log output for a user's radio button selection is always one step behind. This occurs even though I have initially set the default radio button selection to "all". For example, when a user cli ...

Animating progress bars using React Native

I've been working on implementing a progress bar for my react-native project that can be used in multiple instances. Here's the code I currently have: The progress bar tsx: import React, { useEffect } from 'react' import { Animated, St ...

Standards for coding across different languages

As I work on developing a framework that accommodates both C# and TypeScript, I am faced with an interesting dilemma. Take, for instance, the Validator class in C#: class Validator { public bool Validate(string value) { return someConditi ...

The resolution of Angular 8 resolver remains unresolved

I tried using console.log in both the constructor and ngOnInit() of Resolver but for some reason, they are not being logged. resolve:{serverResolver:ServerResolverDynamicDataService}}, console.log("ServerResolverDynamicDataService constructor"); console ...

Ways to implement material-ui button design on an HTML-native button

I am using pure-react-carousel which provides me an unstyled HTML button (ButtonBack). I would like to customize its style using material-ui. Trying to nest buttons within buttons is considered not allowed. An approach that works is manually assigning th ...

Error: The selected module is not a valid top-level option

I am facing an issue while using the babel-loader. I have removed all irrelevant code and just kept the error-related portion. What could be causing this problem? module.exports = merge(baseWebpackConfig, { ... module: { rules: [ ...