diff --git a/projects/demo/src/app/pages/modules/search/search.page.ts b/projects/demo/src/app/pages/modules/search/search.page.ts
index d0e93cd09..bd01cd3ee 100644
--- a/projects/demo/src/app/pages/modules/search/search.page.ts
+++ b/projects/demo/src/app/pages/modules/search/search.page.ts
@@ -6,12 +6,14 @@ import { AlertModal } from "../../../modals/alert.modal";
const exampleStandardTemplate = `
Has icon?
+ Allow empty query?
`;
@@ -57,6 +59,18 @@ export class SearchPage {
description: "Sets whether or not the search displays an icon.",
defaultValue: "true"
},
+ {
+ name: "allowEmptyQuery",
+ type: "boolean",
+ description: "Sets whether the search element display result with empty query.",
+ defaultValue: "false"
+ },
+ {
+ name: "resetQueryOnChange",
+ type: "boolean",
+ description: "Sets whether the query is reset if options change.",
+ defaultValue: "true"
+ },
{
name: "options",
type: "T[]",
@@ -165,6 +179,7 @@ export class SearchExampleStandard {
"Yellow", "Zebra"];
public hasIcon:boolean = true;
+ public allowEmptyQuery:boolean = true;
public get options():string[] {
return SearchExampleStandard.standardOptions;
diff --git a/projects/lib/src/lib/modules/popup/public.ts b/projects/lib/src/lib/modules/popup/public.ts
index 21536b4c0..35f60f172 100644
--- a/projects/lib/src/lib/modules/popup/public.ts
+++ b/projects/lib/src/lib/modules/popup/public.ts
@@ -8,6 +8,8 @@ export {
PopupTrigger,
SuiPopupDirective,
SuiPopup,
+ SuiPopupController,
+ SuiPopupTemplateController,
} from "./internal";
import { PositioningPlacement } from "../../misc/util/internal";
diff --git a/projects/lib/src/lib/modules/search/components/search.ts b/projects/lib/src/lib/modules/search/components/search.ts
index d0e92ce59..1f3279dcb 100644
--- a/projects/lib/src/lib/modules/search/components/search.ts
+++ b/projects/lib/src/lib/modules/search/components/search.ts
@@ -77,6 +77,23 @@ export class SuiSearch implements AfterViewInit {
@Input()
public hasIcon:boolean;
+ // Sets whether the query is reset if options change.
+ @Input()
+ public set resetQueryOnChange(resetQueryOnChange:boolean) {
+ this.searchService.resetQueryOnChange = resetQueryOnChange;
+ }
+
+ // Sets whether the search element display result with empty query.
+ @Input()
+ public set allowEmptyQuery(allowEmptyQuery:boolean) {
+ this._allowEmptyQuery = allowEmptyQuery;
+ this.searchService.allowEmptyQuery = allowEmptyQuery;
+ }
+ public get allowEmptyQuery():boolean {
+ return this._allowEmptyQuery;
+ }
+
+ private _allowEmptyQuery!:boolean;
private _placeholder!:string;
// Gets & sets the placeholder text displayed inside the text input.
@@ -106,7 +123,7 @@ export class SuiSearch implements AfterViewInit {
// Initialise a delayed search.
this.searchService.updateQueryDelayed(query, () =>
// Set the results open state depending on whether a query has been entered.
- this.dropdownService.setOpenState(this.searchService.query.length > 0));
+ this.dropdownService.setOpenState(this.searchService.query.length > 0 || this.allowEmptyQuery));
}
@Input()
@@ -196,6 +213,8 @@ export class SuiSearch implements AfterViewInit {
this.hasClasses = true;
this.tabindex = 0;
this.hasIcon = true;
+ this.allowEmptyQuery = false;
+ this.resetQueryOnChange = true;
this.retainSelectedResult = true;
this.searchDelay = 200;
this.maxResults = 7;
@@ -239,7 +258,7 @@ export class SuiSearch implements AfterViewInit {
}
private open():void {
- if (this.searchService.query.length > 0) {
+ if (this.searchService.query.length > 0 || this.allowEmptyQuery) {
// Only open on click when there is a query entered.
this.dropdownService.setOpenState(true);
}
@@ -247,7 +266,6 @@ export class SuiSearch implements AfterViewInit {
@HostListener("focusout", ["$event"])
public onFocusOut(e:IFocusEvent):void {
- console.log(e);
if (!this._element.nativeElement.contains(e.relatedTarget)) {
this.dropdownService.setOpenState(false);
}
diff --git a/projects/lib/src/lib/modules/search/services/search.service.ts b/projects/lib/src/lib/modules/search/services/search.service.ts
index be71997ea..a83a96b74 100644
--- a/projects/lib/src/lib/modules/search/services/search.service.ts
+++ b/projects/lib/src/lib/modules/search/services/search.service.ts
@@ -59,7 +59,9 @@ export class SearchService {
return this._results;
}
- private _query!:string;
+ private _query:string;
+ // Allows the query to be empty when the options change.
+ public resetQueryOnChange:boolean;
// Allows the empty query to produce results.
public allowEmptyQuery:boolean;
// How long to delay the search for when using updateQueryDelayed. Stored in ms.
@@ -77,7 +79,7 @@ export class SearchService {
return this._isSearching;
}
- constructor(allowEmptyQuery:boolean = false) {
+ constructor(allowEmptyQuery = false) {
this._options = [];
this.optionsFilter = (os, q) => {
// Convert the query string to a RegExp.
@@ -99,6 +101,8 @@ export class SearchService {
// Set default values and reset.
this.allowEmptyQuery = allowEmptyQuery;
+ this._query = "";
+ this.resetQueryOnChange = true;
this.searchDelay = 0;
this.reset();
}
@@ -203,6 +207,10 @@ export class SearchService {
this._results = [];
this._resultsCache = {};
this._isSearching = false;
- this.updateQuery("");
+ if (this.resetQueryOnChange || !this.query) {
+ this.updateQuery("");
+ } else {
+ this.updateQuery(this.query);
+ }
}
}
diff --git a/projects/lib/src/lib/modules/select/classes/select-base.ts b/projects/lib/src/lib/modules/select/classes/select-base.ts
index 0fb73e419..f5e7774d8 100644
--- a/projects/lib/src/lib/modules/select/classes/select-base.ts
+++ b/projects/lib/src/lib/modules/select/classes/select-base.ts
@@ -1,6 +1,6 @@
import {
ViewChild, HostBinding, ElementRef, HostListener, Input, ContentChildren, QueryList,
- AfterContentInit, TemplateRef, ViewContainerRef, ContentChild, EventEmitter, Output, OnDestroy, Directive
+ AfterViewInit, TemplateRef, ViewContainerRef, ContentChild, EventEmitter, Output, OnDestroy, Directive
} from "@angular/core";
import { Subscription } from "rxjs";
import { DropdownService, SuiDropdownMenu } from "../../dropdown/internal";
@@ -17,11 +17,11 @@ export interface IOptionContext extends ITemplateRefContext {
// We use generic type T to specify the type of the options we are working with,
// and U to specify the type of the property of the option used as the value.
@Directive()
-export abstract class SuiSelectBase implements AfterContentInit, OnDestroy {
+export abstract class SuiSelectBase implements AfterViewInit, OnDestroy {
public dropdownService:DropdownService;
public searchService:SearchService;
- @ViewChild(SuiDropdownMenu, { static: true })
+ @ViewChild(SuiDropdownMenu)
protected _menu!:SuiDropdownMenu;
// Keep track of all of the rendered select options. (Rendered by the user using *ngFor).
@@ -43,7 +43,10 @@ export abstract class SuiSelectBase implements AfterContentInit, OnDestroy
@HostBinding("class.visible")
public get isVisible():boolean {
- return this._menu.isVisible;
+ if (this._menu) {
+ return this._menu.isVisible;
+ }
+ return false;
}
@Input()
@@ -246,7 +249,7 @@ export abstract class SuiSelectBase implements AfterContentInit, OnDestroy
this.hasClasses = true;
}
- public ngAfterContentInit():void {
+ public ngAfterViewInit():void {
this._menu.service = this.dropdownService;
// We manually specify the menu items to the menu because the @ContentChildren doesn't pick up our dynamically rendered items.
this._menu.items = this._renderedOptions;
@@ -287,7 +290,7 @@ export abstract class SuiSelectBase implements AfterContentInit, OnDestroy
// The search delay is set to the transition duration to ensure results
// aren't rendered as the select closes as that causes a sudden flash.
if (delayed) {
- this.searchService.searchDelay = this._menu.menuTransitionDuration;
+ this.searchService.searchDelay = this._menu?.menuTransitionDuration;
this.searchService.updateQueryDelayed("");
} else {
this.searchService.updateQuery("");