diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index c74df6d4..0cccfb93 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -149,6 +149,9 @@ export const appRoutes: Route[] = [ // TailwindCSS {path: 'tailwindcss', loadChildren: () => import('app/modules/admin/ui/tailwindcss/tailwindcss.module').then(m => m.TailwindCSSModule)}, + // Advanced search + {path: 'advanced-search', loadChildren: () => import('app/modules/admin/ui/advanced-search/advanced-search.module').then(m => m.AdvancedSearchModule)}, + // Animations {path: 'animations', loadChildren: () => import('app/modules/admin/ui/animations/animations.module').then(m => m.AnimationsModule)}, diff --git a/src/app/mock-api/common/navigation/data.ts b/src/app/mock-api/common/navigation/data.ts index f10fe228..26b22d3f 100644 --- a/src/app/mock-api/common/navigation/data.ts +++ b/src/app/mock-api/common/navigation/data.ts @@ -695,6 +695,13 @@ export const defaultNavigation: FuseNavigationItem[] = [ icon : 'heroicons_outline:sparkles', link : '/ui/tailwindcss' }, + { + id : 'user-interface.advanced-search', + title: 'Advanced search', + type : 'basic', + icon : 'heroicons_outline:search-circle', + link : '/ui/advanced-search' + }, { id : 'user-interface.animations', title: 'Animations', diff --git a/src/app/modules/admin/ui/advanced-search/advanced-search.component.html b/src/app/modules/admin/ui/advanced-search/advanced-search.component.html new file mode 100644 index 00000000..318f0387 --- /dev/null +++ b/src/app/modules/admin/ui/advanced-search/advanced-search.component.html @@ -0,0 +1,114 @@ +
+ + +
+
+ +
+
+ User Interface +
+
+ +
+

+ Advanced Search +

+
+
+
+ + +
+ +
+
+

+ This page demonstrates a query parameters based search using Angular's built-in routerLink directive and its + queryParams input. +

+

+ Fill the form, hit the Search button and then observe the address bar of your browser. If you reload the + page with the parameters, you will see that the form will be populated automatically. We also added an output window so + you can observe the query parameters object. +

+

+ This method can be used for implementing Advanced search mechanics as well as Filtering similar to the + products filtering that you can find in most eCommerce websites. +

+
+ + +
+ + + + Keywords + + + + + + Type + + Any + Files + Folders + + + +
+ + + In trash + + + + + Archived + + + + + Starred + +
+ + +
+ + +
+
+ + +
+ +
+
+
+
diff --git a/src/app/modules/admin/ui/advanced-search/advanced-search.component.ts b/src/app/modules/admin/ui/advanced-search/advanced-search.component.ts new file mode 100644 index 00000000..d0f3e8e2 --- /dev/null +++ b/src/app/modules/admin/ui/advanced-search/advanced-search.component.ts @@ -0,0 +1,108 @@ +import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector : 'advanced-search', + templateUrl : './advanced-search.component.html', + encapsulation : ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AdvancedSearchComponent implements OnInit, OnDestroy +{ + searchForm: FormGroup; + searchFormDefaults: any = { + keywords : '', + type : 'any', + isTrashed : false, + isArchived: false, + isStarred : false + }; + queryParams: Params; + private _unsubscribeAll: Subject = new Subject(); + + /** + * Constructor + */ + constructor( + private _activatedRoute: ActivatedRoute, + private _formBuilder: FormBuilder, + private _router: Router + ) + { + // Prepare the search form with defaults + this.searchForm = this._formBuilder.group({ + keywords : [this.searchFormDefaults.keywords], + type : [this.searchFormDefaults.type], + isTrashed : [this.searchFormDefaults.isTrashed], + isArchived: [this.searchFormDefaults.isArchived], + isStarred : [this.searchFormDefaults.isStarred] + }); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Lifecycle hooks + // ----------------------------------------------------------------------------------------------------- + + /** + * On init + */ + ngOnInit(): void + { + // Subscribe to query params change + this._activatedRoute.queryParams + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe((queryParams) => { + + // Store the query params + this.queryParams = queryParams; + + // Fill the form with the values from query + // params without emitting any form events + this.searchForm.setValue({ + keywords : queryParams?.keywords ?? this.searchFormDefaults.keywords, + type : queryParams?.type ?? this.searchFormDefaults.type, + isTrashed : queryParams?.isTrashed ? coerceBooleanProperty(queryParams?.isTrashed) : this.searchFormDefaults.isTrashed, + isArchived: queryParams?.isArchived ? coerceBooleanProperty(queryParams?.isArchived) : this.searchFormDefaults.isArchived, + isStarred : queryParams?.isStarred ? coerceBooleanProperty(queryParams?.isStarred) : this.searchFormDefaults.isStarred + }, {emitEvent: false}); + }); + } + + /** + * On destroy + */ + ngOnDestroy(): void + { + // Unsubscribe from all subscriptions + this._unsubscribeAll.next(); + this._unsubscribeAll.complete(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Reset the search form using the default + */ + reset(): void + { + this.searchForm.reset(this.searchFormDefaults); + } + + /** + * Perform the search + */ + search(): void + { + // Add query params using the router + this._router.navigate(['./'], { + queryParams: this.searchForm.value, + relativeTo : this._activatedRoute + }); + } +} diff --git a/src/app/modules/admin/ui/advanced-search/advanced-search.module.ts b/src/app/modules/admin/ui/advanced-search/advanced-search.module.ts new file mode 100644 index 00000000..bea58f5c --- /dev/null +++ b/src/app/modules/admin/ui/advanced-search/advanced-search.module.ts @@ -0,0 +1,32 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { FuseHighlightModule } from '@fuse/components/highlight'; +import { SharedModule } from 'app/shared/shared.module'; +import { AdvancedSearchComponent } from 'app/modules/admin/ui/advanced-search/advanced-search.component'; +import { advancedSearchRoutes } from 'app/modules/admin/ui/advanced-search/advanced-search.routing'; + +@NgModule({ + declarations: [ + AdvancedSearchComponent + ], + imports : [ + RouterModule.forChild(advancedSearchRoutes), + MatButtonModule, + MatCheckboxModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatSelectModule, + FuseHighlightModule, + SharedModule + ] +}) +export class AdvancedSearchModule +{ +} diff --git a/src/app/modules/admin/ui/advanced-search/advanced-search.routing.ts b/src/app/modules/admin/ui/advanced-search/advanced-search.routing.ts new file mode 100644 index 00000000..47df94ab --- /dev/null +++ b/src/app/modules/admin/ui/advanced-search/advanced-search.routing.ts @@ -0,0 +1,9 @@ +import { Route } from '@angular/router'; +import { AdvancedSearchComponent } from 'app/modules/admin/ui/advanced-search/advanced-search.component'; + +export const advancedSearchRoutes: Route[] = [ + { + path : '', + component: AdvancedSearchComponent + } +];