@@ -17,6 +17,7 @@ import {
1717 InjectionToken ,
1818 Injector ,
1919 input ,
20+ linkedSignal ,
2021 model ,
2122 numberAttribute ,
2223 OnChanges ,
@@ -105,63 +106,161 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
105106
106107 // signals
107108 public readonly _disabled = signal < boolean > ( false ) ;
108- // inputs
109- readonly ariaLabelDropdown = input < string > ( undefined ) ;
110- readonly ariaLabel = input < string | undefined > ( undefined ) ;
111- readonly markFirst = input ( true , { transform : booleanAttribute } ) ;
112- readonly placeholder = input < string > ( this . config . placeholder ) ;
113- readonly fixedPlaceholder = input < boolean > ( true ) ;
114- readonly notFoundText = input < string > ( undefined ) ;
115- readonly typeToSearchText = input < string > ( undefined ) ;
116- readonly preventToggleOnRightClick = input < boolean > ( false ) ;
117- readonly addTagText = input < string > ( undefined ) ;
118- readonly loadingText = input < string > ( undefined ) ;
119- readonly clearAllText = input < string > ( undefined ) ;
120- readonly dropdownPosition = input < DropdownPosition > ( 'auto' ) ;
121- readonly appendTo = input < string > ( undefined ) ;
122- readonly outsideClickEvent = input < 'click' | 'mousedown' > ( this . config . outsideClickEvent ) ;
123- readonly loading = input ( false , { transform : booleanAttribute } ) ;
124- readonly closeOnSelect = input ( true , { transform : booleanAttribute } ) ;
125- readonly hideSelected = input ( false , { transform : booleanAttribute } ) ;
126- readonly selectOnTab = input ( false , { transform : booleanAttribute } ) ;
127- readonly openOnEnter = input ( undefined , { transform : booleanAttribute } ) ;
128- readonly maxSelectedItems = input < number , unknown > ( undefined , { transform : numberAttribute } ) ;
129- readonly groupBy = input < string | ( ( value : any ) => any ) > ( undefined ) ;
130- readonly groupValue = input < GroupValueFn > ( undefined ) ;
131- readonly bufferAmount = input ( 4 , { transform : numberAttribute } ) ;
132- readonly virtualScroll = input < boolean , unknown > ( undefined , { transform : booleanAttribute } ) ;
133- readonly selectableGroup = input ( false , { transform : booleanAttribute } ) ;
134- readonly tabFocusOnClearButton = input < boolean | undefined > ( ) ;
135- readonly selectableGroupAsModel = input ( true , { transform : booleanAttribute } ) ;
136- readonly searchFn = input ( null ) ;
137- readonly trackByFn = input ( null ) ;
138- readonly clearOnBackspace = input ( true , { transform : booleanAttribute } ) ;
139- readonly labelForId = input ( null ) ;
140- readonly inputAttrs = input < Record < string , string > > ( { } ) ;
141- readonly tabIndex = input < number , unknown > ( undefined , { transform : numberAttribute } ) ;
142- readonly readonly = input ( false , { transform : booleanAttribute } ) ;
143- readonly searchWhileComposing = input ( true , { transform : booleanAttribute } ) ;
144- readonly minTermLength = input ( 0 , { transform : numberAttribute } ) ;
145- readonly editableSearchTerm = input ( false , { transform : booleanAttribute } ) ;
146- readonly ngClass = input ( null ) ;
147- readonly typeahead = input < Subject < string > > ( undefined ) ;
148- readonly multiple = input ( false , { transform : booleanAttribute } ) ;
149- readonly addTag = input < boolean | AddTagFn > ( false ) ;
150- readonly searchable = input ( true , { transform : booleanAttribute } ) ;
151- readonly clearable = input ( true , { transform : booleanAttribute } ) ;
152- readonly clearKeepsDisabledOptions = input ( true , { transform : booleanAttribute } ) ;
153- readonly deselectOnClick = input < boolean > ( ) ;
154- readonly clearSearchOnAdd = input ( undefined ) ;
155- readonly compareWith = input ( undefined , {
109+ // inputs: underscored input() + alias + linkedSignal() for stable public names (back compat)
110+ readonly _ariaLabelDropdown = input < string > ( undefined , { alias : 'ariaLabelDropdown' } ) ;
111+ readonly ariaLabelDropdown = linkedSignal ( ( ) => this . _ariaLabelDropdown ( ) ) ;
112+
113+ readonly _ariaLabel = input < string | undefined > ( undefined , { alias : 'ariaLabel' } ) ;
114+ readonly ariaLabel = linkedSignal ( ( ) => this . _ariaLabel ( ) ) ;
115+
116+ readonly _markFirst = input ( true , { alias : 'markFirst' , transform : booleanAttribute } ) ;
117+ readonly markFirst = linkedSignal ( ( ) => this . _markFirst ( ) ) ;
118+
119+ readonly _placeholder = input < string > ( this . config . placeholder , { alias : 'placeholder' } ) ;
120+ readonly placeholder = linkedSignal ( ( ) => this . _placeholder ( ) ) ;
121+
122+ readonly _fixedPlaceholder = input < boolean > ( true , { alias : 'fixedPlaceholder' } ) ;
123+ readonly fixedPlaceholder = linkedSignal ( ( ) => this . _fixedPlaceholder ( ) ) ;
124+
125+ readonly _notFoundText = input < string > ( undefined , { alias : 'notFoundText' } ) ;
126+ readonly notFoundText = linkedSignal ( ( ) => this . _notFoundText ( ) ) ;
127+
128+ readonly _typeToSearchText = input < string > ( undefined , { alias : 'typeToSearchText' } ) ;
129+ readonly typeToSearchText = linkedSignal ( ( ) => this . _typeToSearchText ( ) ) ;
130+
131+ readonly _preventToggleOnRightClick = input < boolean > ( false , { alias : 'preventToggleOnRightClick' } ) ;
132+ readonly preventToggleOnRightClick = linkedSignal ( ( ) => this . _preventToggleOnRightClick ( ) ) ;
133+
134+ readonly _addTagText = input < string > ( undefined , { alias : 'addTagText' } ) ;
135+ readonly addTagText = linkedSignal ( ( ) => this . _addTagText ( ) ) ;
136+
137+ readonly _loadingText = input < string > ( undefined , { alias : 'loadingText' } ) ;
138+ readonly loadingText = linkedSignal ( ( ) => this . _loadingText ( ) ) ;
139+
140+ readonly _clearAllText = input < string > ( undefined , { alias : 'clearAllText' } ) ;
141+ readonly clearAllText = linkedSignal ( ( ) => this . _clearAllText ( ) ) ;
142+
143+ readonly _dropdownPosition = input < DropdownPosition > ( 'auto' , { alias : 'dropdownPosition' } ) ;
144+ readonly dropdownPosition = linkedSignal ( ( ) => this . _dropdownPosition ( ) ) ;
145+
146+ readonly _appendTo = input < string > ( undefined , { alias : 'appendTo' } ) ;
147+ readonly appendTo = linkedSignal ( ( ) => this . _appendTo ( ) ) ;
148+
149+ readonly _outsideClickEvent = input < 'click' | 'mousedown' > ( this . config . outsideClickEvent , { alias : 'outsideClickEvent' } ) ;
150+ readonly outsideClickEvent = linkedSignal ( ( ) => this . _outsideClickEvent ( ) ) ;
151+
152+ readonly _loading = input ( false , { alias : 'loading' , transform : booleanAttribute } ) ;
153+ readonly loading = linkedSignal ( ( ) => this . _loading ( ) ) ;
154+
155+ readonly _closeOnSelect = input ( true , { alias : 'closeOnSelect' , transform : booleanAttribute } ) ;
156+ readonly closeOnSelect = linkedSignal ( ( ) => this . _closeOnSelect ( ) ) ;
157+
158+ readonly _hideSelected = input ( false , { alias : 'hideSelected' , transform : booleanAttribute } ) ;
159+ readonly hideSelected = linkedSignal ( ( ) => this . _hideSelected ( ) ) ;
160+
161+ readonly _selectOnTab = input ( false , { alias : 'selectOnTab' , transform : booleanAttribute } ) ;
162+ readonly selectOnTab = linkedSignal ( ( ) => this . _selectOnTab ( ) ) ;
163+
164+ readonly _openOnEnter = input ( undefined , { alias : 'openOnEnter' , transform : booleanAttribute } ) ;
165+ readonly openOnEnter = linkedSignal ( ( ) => this . _openOnEnter ( ) ) ;
166+
167+ readonly _maxSelectedItems = input < number , unknown > ( undefined , { alias : 'maxSelectedItems' , transform : numberAttribute } ) ;
168+ readonly maxSelectedItems = linkedSignal ( ( ) => this . _maxSelectedItems ( ) ) ;
169+
170+ readonly _groupBy = input < string | ( ( value : any ) => any ) > ( undefined , { alias : 'groupBy' } ) ;
171+ readonly groupBy = linkedSignal ( ( ) => this . _groupBy ( ) ) ;
172+
173+ readonly _groupValue = input < GroupValueFn > ( undefined , { alias : 'groupValue' } ) ;
174+ readonly groupValue = linkedSignal ( ( ) => this . _groupValue ( ) ) ;
175+
176+ readonly _bufferAmount = input ( 4 , { alias : 'bufferAmount' , transform : numberAttribute } ) ;
177+ readonly bufferAmount = linkedSignal ( ( ) => this . _bufferAmount ( ) ) ;
178+
179+ readonly _virtualScroll = input < boolean , unknown > ( undefined , { alias : 'virtualScroll' , transform : booleanAttribute } ) ;
180+ readonly virtualScroll = linkedSignal ( ( ) => this . _virtualScroll ( ) ) ;
181+
182+ readonly _selectableGroup = input ( false , { alias : 'selectableGroup' , transform : booleanAttribute } ) ;
183+ readonly selectableGroup = linkedSignal ( ( ) => this . _selectableGroup ( ) ) ;
184+
185+ readonly _tabFocusOnClearButton = input < boolean | undefined > ( undefined , { alias : 'tabFocusOnClearButton' } ) ;
186+ readonly tabFocusOnClearButton = linkedSignal ( ( ) => this . _tabFocusOnClearButton ( ) ) ;
187+
188+ readonly _selectableGroupAsModel = input ( true , { alias : 'selectableGroupAsModel' , transform : booleanAttribute } ) ;
189+ readonly selectableGroupAsModel = linkedSignal ( ( ) => this . _selectableGroupAsModel ( ) ) ;
190+
191+ readonly _searchFn = input ( null , { alias : 'searchFn' } ) ;
192+ readonly searchFn = linkedSignal ( ( ) => this . _searchFn ( ) ) ;
193+
194+ readonly _trackByFn = input ( null , { alias : 'trackByFn' } ) ;
195+ readonly trackByFn = linkedSignal ( ( ) => this . _trackByFn ( ) ) ;
196+
197+ readonly _clearOnBackspace = input ( true , { alias : 'clearOnBackspace' , transform : booleanAttribute } ) ;
198+ readonly clearOnBackspace = linkedSignal ( ( ) => this . _clearOnBackspace ( ) ) ;
199+
200+ readonly _labelForId = input ( null , { alias : 'labelForId' } ) ;
201+ readonly labelForId = linkedSignal ( ( ) => this . _labelForId ( ) ) ;
202+
203+ readonly _inputAttrs = input < Record < string , string > > ( { } , { alias : 'inputAttrs' } ) ;
204+ readonly inputAttrs = linkedSignal ( ( ) => this . _inputAttrs ( ) ) ;
205+
206+ readonly _tabIndex = input < number , unknown > ( undefined , { alias : 'tabIndex' , transform : numberAttribute } ) ;
207+ readonly tabIndex = linkedSignal ( ( ) => this . _tabIndex ( ) ) ;
208+
209+ readonly _readonly = input ( false , { alias : 'readonly' , transform : booleanAttribute } ) ;
210+ readonly readonly = linkedSignal ( ( ) => this . _readonly ( ) ) ;
211+
212+ readonly _searchWhileComposing = input ( true , { alias : 'searchWhileComposing' , transform : booleanAttribute } ) ;
213+ readonly searchWhileComposing = linkedSignal ( ( ) => this . _searchWhileComposing ( ) ) ;
214+
215+ readonly _minTermLength = input ( 0 , { alias : 'minTermLength' , transform : numberAttribute } ) ;
216+ readonly minTermLength = linkedSignal ( ( ) => this . _minTermLength ( ) ) ;
217+
218+ readonly _editableSearchTerm = input ( false , { alias : 'editableSearchTerm' , transform : booleanAttribute } ) ;
219+ readonly editableSearchTerm = linkedSignal ( ( ) => this . _editableSearchTerm ( ) ) ;
220+
221+ readonly _ngClass = input ( null , { alias : 'ngClass' } ) ;
222+ readonly ngClass = linkedSignal ( ( ) => this . _ngClass ( ) ) ;
223+
224+ readonly _typeahead = input < Subject < string > > ( undefined , { alias : 'typeahead' } ) ;
225+ readonly typeahead = linkedSignal ( ( ) => this . _typeahead ( ) ) ;
226+
227+ readonly _multiple = input ( false , { alias : 'multiple' , transform : booleanAttribute } ) ;
228+ readonly multiple = linkedSignal ( ( ) => this . _multiple ( ) ) ;
229+
230+ readonly _addTag = input < boolean | AddTagFn > ( false , { alias : 'addTag' } ) ;
231+ readonly addTag = linkedSignal ( ( ) => this . _addTag ( ) ) ;
232+
233+ readonly _searchable = input ( true , { alias : 'searchable' , transform : booleanAttribute } ) ;
234+ readonly searchable = linkedSignal ( ( ) => this . _searchable ( ) ) ;
235+
236+ readonly _clearable = input ( true , { alias : 'clearable' , transform : booleanAttribute } ) ;
237+ readonly clearable = linkedSignal ( ( ) => this . _clearable ( ) ) ;
238+
239+ readonly _clearKeepsDisabledOptions = input ( true , { alias : 'clearKeepsDisabledOptions' , transform : booleanAttribute } ) ;
240+ readonly clearKeepsDisabledOptions = linkedSignal ( ( ) => this . _clearKeepsDisabledOptions ( ) ) ;
241+
242+ readonly _deselectOnClick = input < boolean > ( undefined , { alias : 'deselectOnClick' } ) ;
243+ readonly deselectOnClick = linkedSignal ( ( ) => this . _deselectOnClick ( ) ) ;
244+
245+ readonly _clearSearchOnAdd = input ( undefined , { alias : 'clearSearchOnAdd' } ) ;
246+ readonly clearSearchOnAdd = linkedSignal ( ( ) => this . _clearSearchOnAdd ( ) ) ;
247+
248+ readonly _compareWith = input ( undefined , {
249+ alias : 'compareWith' ,
156250 transform : ( fn : CompareWithFn | undefined ) => {
157251 if ( fn !== undefined && fn !== null && ! isFunction ( fn ) ) {
158252 throw Error ( '`compareWith` must be a function.' ) ;
159253 }
160254 return fn ;
161255 } ,
162256 } ) ;
163- readonly keyDownFn = input < ( _ : KeyboardEvent ) => boolean > ( ( _ : KeyboardEvent ) => true ) ;
164- readonly popover = input ( false , { transform : booleanAttribute } ) ;
257+ readonly compareWith = linkedSignal ( ( ) => this . _compareWith ( ) ) ;
258+
259+ readonly _keyDownFn = input < ( _ : KeyboardEvent ) => boolean > ( ( _ : KeyboardEvent ) => true , { alias : 'keyDownFn' } ) ;
260+ readonly keyDownFn = linkedSignal ( ( ) => this . _keyDownFn ( ) ) ;
261+
262+ readonly _popover = input ( false , { alias : 'popover' , transform : booleanAttribute } ) ;
263+ readonly popover = linkedSignal ( ( ) => this . _popover ( ) ) ;
165264
166265 // models
167266 readonly bindLabel = model < string > ( undefined ) ;
@@ -241,7 +340,7 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
241340 private readonly autoFocus = inject ( new HostAttributeToken ( 'autofocus' ) , { optional : true } ) ;
242341 // private variables
243342 private readonly _defaultLabel = 'label' ;
244- private readonly _editableSearchTerm = computed ( ( ) => this . editableSearchTerm ( ) && ! this . multiple ( ) ) ;
343+ private readonly _editableSearchTermActive = computed ( ( ) => this . editableSearchTerm ( ) && ! this . multiple ( ) ) ;
245344 private _focused : boolean ;
246345 private _injector = inject ( Injector ) ;
247346 private _isComposing = false ;
@@ -482,7 +581,7 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
482581 writeValue ( value : any | any [ ] ) : void {
483582 this . itemsList . clearSelected ( false ) ;
484583 this . _handleWriteValue ( value ) ;
485- if ( this . _editableSearchTerm ( ) ) {
584+ if ( this . _editableSearchTermActive ( ) ) {
486585 this . _setSearchTermFromItems ( ) ;
487586 }
488587 this . _cd . markForCheck ( ) ;
@@ -532,7 +631,7 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
532631 }
533632 this . isOpen . set ( false ) ;
534633 this . _isComposing = false ;
535- if ( ! this . _editableSearchTerm ( ) ) {
634+ if ( ! this . _editableSearchTermActive ( ) ) {
536635 this . _clearSearch ( ) ;
537636 } else {
538637 this . itemsList . resetFilteredItems ( ) ;
@@ -554,15 +653,15 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
554653 this . select ( item ) ;
555654 }
556655
557- if ( this . _editableSearchTerm ( ) ) {
656+ if ( this . _editableSearchTermActive ( ) ) {
558657 this . _setSearchTermFromItems ( ) ;
559658 }
560659 }
561660
562661 select ( item : NgOption ) {
563662 if ( ! item . selected ) {
564663 this . itemsList . select ( item ) ;
565- if ( this . clearSearchOnAddValue ( ) && ! this . _editableSearchTerm ( ) ) {
664+ if ( this . clearSearchOnAddValue ( ) && ! this . _editableSearchTermActive ( ) ) {
566665 this . _clearSearch ( ) ;
567666 }
568667
@@ -688,7 +787,7 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
688787 return ;
689788 }
690789
691- if ( this . _editableSearchTerm ( ) ) {
790+ if ( this . _editableSearchTermActive ( ) ) {
692791 this . _setSearchTermFromItems ( ) ;
693792 }
694793
@@ -703,7 +802,7 @@ export class NgSelectComponent implements OnChanges, OnInit, AfterViewInit, Cont
703802 if ( ! this . isOpen ( ) && ! this . disabled ( ) ) {
704803 this . _onTouched ( ) ;
705804 }
706- if ( this . _editableSearchTerm ( ) ) {
805+ if ( this . _editableSearchTermActive ( ) ) {
707806 this . _setSearchTermFromItems ( ) ;
708807 }
709808 this . _focused = false ;
0 commit comments