mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-01-09 12:05:08 +00:00
(ui/advanced-search) Added an example search form that uses query parameters for Advanced Search forms
This commit is contained in:
parent
11ad2c89df
commit
bb57ec2324
|
@ -149,6 +149,9 @@ export const appRoutes: Route[] = [
|
||||||
// TailwindCSS
|
// TailwindCSS
|
||||||
{path: 'tailwindcss', loadChildren: () => import('app/modules/admin/ui/tailwindcss/tailwindcss.module').then(m => m.TailwindCSSModule)},
|
{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
|
// Animations
|
||||||
{path: 'animations', loadChildren: () => import('app/modules/admin/ui/animations/animations.module').then(m => m.AnimationsModule)},
|
{path: 'animations', loadChildren: () => import('app/modules/admin/ui/animations/animations.module').then(m => m.AnimationsModule)},
|
||||||
|
|
||||||
|
|
|
@ -695,6 +695,13 @@ export const defaultNavigation: FuseNavigationItem[] = [
|
||||||
icon : 'heroicons_outline:sparkles',
|
icon : 'heroicons_outline:sparkles',
|
||||||
link : '/ui/tailwindcss'
|
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',
|
id : 'user-interface.animations',
|
||||||
title: 'Animations',
|
title: 'Animations',
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
<div class="flex flex-col flex-auto min-w-0">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex flex-col sm:flex-row flex-0 sm:items-center sm:justify-between p-6 sm:py-8 sm:px-10 border-b bg-card dark:bg-transparent">
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="flex flex-wrap items-center font-medium">
|
||||||
|
<div>
|
||||||
|
<a class="whitespace-nowrap text-primary-500">User Interface</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="mt-2">
|
||||||
|
<h2 class="text-3xl md:text-4xl font-extrabold tracking-tight leading-7 sm:leading-10 truncate">
|
||||||
|
Advanced Search
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main -->
|
||||||
|
<div class="flex-auto p-6 sm:p-10">
|
||||||
|
|
||||||
|
<div class="max-w-3xl">
|
||||||
|
<div class="max-w-3xl prose prose-sm">
|
||||||
|
<p>
|
||||||
|
This page demonstrates a query parameters based search using Angular's built-in <code>routerLink</code> directive and its
|
||||||
|
<code>queryParams</code> input.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Fill the form, hit the <strong>Search</strong> 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.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This method can be used for implementing <em>Advanced search</em> mechanics as well as <em>Filtering</em> similar to the
|
||||||
|
products filtering that you can find in most eCommerce websites.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Advanced search form -->
|
||||||
|
<form
|
||||||
|
class="flex flex-col items-start w-full max-w-3xl mt-8 p-8 space-y-8 rounded-2xl shadow overflow-hidden bg-card"
|
||||||
|
[formGroup]="searchForm">
|
||||||
|
|
||||||
|
<!-- Keywords -->
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Keywords</mat-label>
|
||||||
|
<input
|
||||||
|
[autocomplete]="'off'"
|
||||||
|
[formControlName]="'keywords'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- Type -->
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Type</mat-label>
|
||||||
|
<mat-select [formControlName]="'type'">
|
||||||
|
<mat-option [value]="'any'">Any</mat-option>
|
||||||
|
<mat-option [value]="'files'">Files</mat-option>
|
||||||
|
<mat-option [value]="'folders'">Folders</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div class="flex items-center space-x-8">
|
||||||
|
<!-- In trash -->
|
||||||
|
<mat-checkbox
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'isTrashed'">
|
||||||
|
In trash
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<!-- Archived -->
|
||||||
|
<mat-checkbox
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'isArchived'">
|
||||||
|
Archived
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<!-- Starred -->
|
||||||
|
<mat-checkbox
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'isStarred'">
|
||||||
|
Starred
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex items-center justify-end w-full mt-8">
|
||||||
|
<button
|
||||||
|
(click)="reset()"
|
||||||
|
type="button"
|
||||||
|
mat-button>Reset
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="ml-2"
|
||||||
|
(click)="search()"
|
||||||
|
[color]="'primary'"
|
||||||
|
type="button"
|
||||||
|
mat-flat-button>Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Query params as json -->
|
||||||
|
<div class="dark w-full mt-8 p-4 rounded-2xl overflow-hidden">
|
||||||
|
<textarea
|
||||||
|
fuse-highlight
|
||||||
|
[code]="queryParams | json"
|
||||||
|
[lang]="'json'"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -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<any> = new Subject<any>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
{
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
];
|
Loading…
Reference in New Issue
Block a user