[ADF-1876] added custom empty result tag for search result control (#2940)

* [ADF-1876] added custom empty template for no search result

* [ADF-1876] added custom empty result tag for search result control

* [ADF-1876] added custom no search result tag for search control component

* [ADF-1876] added documentation for template no result
This commit is contained in:
Vito 2018-02-13 18:11:09 +00:00 committed by Eugenio Romano
parent 5d3f005b60
commit b3955b3f6c
11 changed files with 167 additions and 6 deletions

View File

@ -1,4 +1,7 @@
<adf-search-control [highlight]="true"
(optionClicked)="onItemClicked($event)"
(submit)="onSearchSubmit($event)">
<!-- <adf-empty-search-result>
<span>I don't want to show you this result</span>
</adf-empty-search-result> -->
</adf-search-control>

View File

@ -47,3 +47,18 @@ Displays a input text which shows find-as-you-type suggestions.
Example of a component that uses the search control. In this example the search term is simply logged to the console
but instead the component could emit an event to be consumed upstream, or it could trigger a change inside a search
results component embedded inside the same component.
## Customizable template for no result
It is possible to customize with your own template what to show when no result are found for the search.
```html
<adf-search-control [highlight]="true"
(optionClicked)="onItemClicked($event)"
(submit)="onSearchSubmit($event)">
<adf-empty-search-result>
<!-- YOUR CUSTOM TEMPLATE HERE -->
<span>YOUR CUSTOM MESSAGE</span>
</adf-empty-search-result>
</adf-search-control>
```
All you need to add is the `adf-empty-search-result` tag in the `adf-search-control` and then put inside the template you want to render when no results are found.

View File

@ -20,3 +20,4 @@ export * from './document-list.component.mock';
export * from './document-list.service.mock';
export * from './search.component.mock';
export * from './search.service.mock';
export * from './search-control.component.mock';

View File

@ -0,0 +1,41 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component } from '@angular/core';
@Component({
template: `
<adf-search-control [highlight]="true">
<adf-empty-search-result>
<span id="custom-no-result">{{customMessage}}</span>
</adf-empty-search-result>
</adf-search-control>
`
})
export class SimpleSearchTestCustomEmptyComponent {
customMessage: string = '';
constructor() {
}
setCustomMessageForNoResult(message: string) {
this.customMessage = message;
}
}

View File

@ -0,0 +1,3 @@
<div class="adf-empty-search-result">
<ng-content></ng-content>
</div>

View File

@ -0,0 +1,25 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'adf-empty-search-result',
templateUrl: './empty-search-result.component.html',
encapsulation: ViewEncapsulation.None
})
export class EmptySearchResultComponent {}

View File

@ -57,11 +57,16 @@
</ng-template>
<p mat-line class="adf-search-fixed-text"> {{item?.entry.createdByUser.displayName}} </p>
</mat-list-item>
<mat-list-item
id="search_no_result"
<mat-list-item id="search_no_result"
data-automation-id="search_no_result_found"
*ngIf="data?.list?.entries.length === 0">
<p mat-line class="adf-search-fixed-text">{{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }}</p>
<ng-content
selector="adf-empty-search-result"
*ngIf="isNoSearchTemplatePresent() else defaultNoResult">
</ng-content>
<ng-template #defaultNoResult>
<p mat-line class="adf-search-fixed-text">{{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }}</p>
</ng-template>
</mat-list-item>
</mat-list>
</ng-template>

View File

@ -26,6 +26,9 @@ import { noResult, results } from '../../mock';
import { SearchControlComponent } from './search-control.component';
import { SearchTriggerDirective } from './search-trigger.directive';
import { SearchComponent } from './search.component';
import { EmptySearchResultComponent } from './empty-search-result.component';
import { SimpleSearchTestCustomEmptyComponent } from '../../mock';
import { SearchModule } from '../../index';
describe('SearchControlComponent', () => {
@ -44,7 +47,8 @@ describe('SearchControlComponent', () => {
declarations: [
SearchControlComponent,
SearchComponent,
SearchTriggerDirective
SearchTriggerDirective,
EmptySearchResultComponent
],
providers: [
ThumbnailService,
@ -543,3 +547,55 @@ describe('SearchControlComponent', () => {
}));
});
});
describe('SearchControlComponent - No result custom', () => {
let fixtureCustom: ComponentFixture<SimpleSearchTestCustomEmptyComponent>;
let elementCustom: HTMLElement;
let componentCustom: SimpleSearchTestCustomEmptyComponent;
let authServiceCustom: AuthenticationService;
let searchServiceCustom: SearchService;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
SearchModule
],
declarations: [
SimpleSearchTestCustomEmptyComponent
]
}).compileComponents().then(() => {
fixtureCustom = TestBed.createComponent(SimpleSearchTestCustomEmptyComponent);
componentCustom = fixtureCustom.componentInstance;
elementCustom = fixtureCustom.nativeElement;
authServiceCustom = TestBed.get(AuthenticationService);
searchServiceCustom = TestBed.get(SearchService);
});
}));
beforeEach(async(() => {
spyOn(authServiceCustom, 'isEcmLoggedIn').and.returnValue(true);
}));
afterEach(async(() => {
fixtureCustom.destroy();
TestBed.resetTestingModule();
}));
it('should display the custom no results when it is configured', async(() => {
const noResultCustomMessage = 'BANDI IS NOTHING';
componentCustom.setCustomMessageForNoResult(noResultCustomMessage);
spyOn(searchServiceCustom, 'search').and.returnValue(Observable.of(noResult));
fixtureCustom.detectChanges();
let inputDebugElement = fixtureCustom.debugElement.query(By.css('#adf-control-input'));
inputDebugElement.nativeElement.value = 'BANDY NOTHING';
inputDebugElement.nativeElement.focus();
inputDebugElement.nativeElement.dispatchEvent(new Event('input'));
fixtureCustom.whenStable().then(() => {
fixtureCustom.detectChanges();
expect(elementCustom.querySelector('#custom-no-result').textContent).toBe(noResultCustomMessage);
});
}));
});

View File

@ -18,12 +18,13 @@
import { AuthenticationService, ThumbnailService } from '@alfresco/adf-core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output,
QueryList, ViewEncapsulation, ViewChild, ViewChildren, ElementRef } from '@angular/core';
QueryList, ViewEncapsulation, ViewChild, ViewChildren, ElementRef, TemplateRef, ContentChild } from '@angular/core';
import { MinimalNodeEntity, QueryBody } from 'alfresco-js-api';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { SearchComponent } from './search.component';
import { MatListItem } from '@angular/material';
import { EmptySearchResultComponent } from './empty-search-result.component';
@Component({
selector: 'adf-search-control',
@ -102,8 +103,12 @@ export class SearchControlComponent implements OnInit, OnDestroy {
@ViewChildren(MatListItem)
private listResultElement: QueryList<MatListItem>;
@ContentChild(EmptySearchResultComponent)
emptySearchTemplate: EmptySearchResultComponent;
searchTerm: string = '';
subscriptAnimationState: string;
noSearchResultTemplate: TemplateRef <any> = null;
private toggleSearch = new Subject<any>();
private focusSubject = new Subject<FocusEvent>();
@ -137,6 +142,10 @@ export class SearchControlComponent implements OnInit, OnDestroy {
this.setupFocusEventHandlers();
}
isNoSearchTemplatePresent(): boolean {
return this.emptySearchTemplate ? true : false;
}
ngOnDestroy(): void {
if (this.focusSubject) {
this.focusSubject.unsubscribe();

View File

@ -18,3 +18,4 @@
export * from './components/search.component';
export * from './components/search-control.component';
export * from './components/search-trigger.directive';
export * from './components/empty-search-result.component';

View File

@ -27,11 +27,13 @@ import { SearchTriggerDirective } from './components/search-trigger.directive';
import { SearchControlComponent } from './components/search-control.component';
import { SearchComponent } from './components/search.component';
import { EmptySearchResultComponent } from './components/empty-search-result.component';
export const ALFRESCO_SEARCH_DIRECTIVES: [any] = [
SearchComponent,
SearchControlComponent,
SearchTriggerDirective
SearchTriggerDirective,
EmptySearchResultComponent
];
export const ALFRESCO_SEARCH_PROVIDERS: [any] = [