ng-select: ng-option with null value causes empty selection

Describe the bug I have a use case where I need to add an option with null value. When the model’s value is null, the selection appears empty.

To Reproduce

<ng-select [(ngModel)]="dimensionalFilters.campaign" (ngModelChange)="generateReport()" 
       [clearable]="false">
       <ng-option [value]="null">Show All</ng-option>
       <ng-option *ngFor="let c of campaigns" [value]="c.id">{{ c.name }}</ng-option>
</ng-select>

Also, when selecting this option, the model is populated with {$ngOptionValue: null, $ngOptionLabel: "Show All", disabled: false}.

Expected behavior Show All should show up as selected and model value should be null.

Screenshots empty-selection

Additional context Using a default select this works as expected. Option is selected and model’s value is set to null when selecting this option.

<select [(ngModel)]="dimensionalFilters.campaign" (ngModelChange)="generateReport()">
    <option [ngValue]="null">Show All</option>
    <option *ngFor="let c of campaigns" [ngValue]="c.id">{{ c.name }}</option>
</select>

default-selection

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 38
  • Comments: 23 (2 by maintainers)

Most upvoted comments

If we add this change it could break a lot of functionality since we treat both null and undefined as empty or cleared state.

You treat wrong! Usage of -1/0/“i’m bad programmer”/etc. instead of null is the worst crutch I ever see.

I think it’s a bug and I think bugs must be fixed!

For breaking changes You can use major versions. To detect breaked of functionality we have testing.

Everything else - recognition of one’s own incompetence and justification of laziness.

Best regards, Boris.

You can have a value something like -1 etc for such case and will will work just fine. If we add this change it could break a lot of functionality since we treat both null and undefined as empty or cleared state.

items = [
   { label: 'Select all', value: -1 }
   { label: 'One', value: 1 }
]

onChange(value) {
   if (value === -1) {
       // Treat the same as with null.
   }
}

Same problem here…

I was dealing with this issue and found a super easy work around. Just add placeholder to your ng-select:

<ng-select [(ngModel)]="foo" (ngModelChange)="generateReport()" [clearable]="false" placeholder="Show All" class="baz">

If you don’t like the lighter color of the placeholder, add this to your css: ::ng-deep .ng-select.baz .ng-select-container .ng-value-container .ng-placeholder { color: #333; }

image

Currently, we treat null and undefined as empty values. E.g.: user clears selection and his ngModel is null.

We probably need to keep null as a valid value and undefined as an empty value since we need to address empty state somehow 🤔

Any progress on this?

@joegitau What was being discussed here is exactly this, whatever number/value you use, it’s completely diferent from “null”. It can’t be acceptable as solution.

Hi, guys. As I can understand problem is in this file on string 227 const value = isDefined(item.$ngOptionValue) ? item.$ngOptionValue : item; It works wrong because of isDefined method looks like export function isDefined(value: any) { return value !== undefined && value !== null; } I think null is defined value and this behavior must be fixed. P.S. Sorry for my bad English.

Any update on this? I see the PR is stale for last 2 weeks, Can I be of any help to expedite this?

I was stuggling with same issue but the below solution works well for me:

      <select class="form-select" id="target-language-select" (change)="setTargetLng($event)">
          <option value="" disabled selected>Target language</option>
          <option *ngFor="let l of languages" [selected]="targetLngId == l.id" value="{{l.id}}">{{languagesList[l.code]?.name}}</option>
      </select>

It’s just select tag instead of ng-select but resolves the issue. Dunno if it works for ng-select as well.

You could first bind the Show All value to some number, say 0. Then convert 0 to null within your class definition - tapping into the Change output event!

So, something like…

<ng-select .... (change)="sanitizeValues($event)">
       <ng-option [value]=0>Show All</ng-option>
       <ng-option *ngFor="let c of campaigns" [value]="c.id">{{ c.name }}</ng-option>
</ng-select>

Then within the template class…

sanitizeValues(value: number): number {
  return value || null;
}