import { Injectable } from '@angular/core' ; import { BehaviorSubject , Subject } from 'rxjs' ; import { SearchBuilderComponentDefinition } from './interfaces/component-definition.interface' ; import { SearchBuilderQuery } from './interfaces/query.interface' ; @ Injectable ( ) export class SearchBuilderService { query : SearchBuilderQuery = { } ; queryChange : Subject < SearchBuilderQuery > = new Subject < SearchBuilderQuery > ( ) ; validationChange : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( true ) ; private _componentId : number = 0 ; private _components : SearchBuilderComponentDefinition [ ] = [ ] ; private _validation : { [ key ] : boolean ; } = { } ; /**
     * Add a component to the internal list of components
     */ registerComponent ( component ) { if ( this . _components . find ( cmp => cmp . name === component . name ) ) { throw new Error ( `Search builder components must have a unique name. The name ${ component . name } has already been used.` ) ; } this . _components . push ( component ) ; } /**
     * Bulk registration of components
     * (Just a helper method)
     */ registerComponents ( components ) { components . forEach ( component => this . registerComponent ( component ) ) ; } /**
     * Get a registered component class
     */ getComponent ( name ) { const component = this . _components . find ( cmp => cmp . name === name ) ; if ( ! component ) { throw new Error ( `No search build component with the name ${ name } exists` ) ; } component . config = component . config || { } ; return component ; } /**
     * Update the internal search query state
     * note that the query will be immutable
     */ setQuery ( query ) { this . query = Object . assign ( { } , query ) ; } /**
     * Return the current query state
     */ getQuery ( ) { return this . query ; } /**
     * Trigger the observable to indicate the query has been updated
     */ queryHasChanged ( ) { this . queryChange . next ( this . query ) ; } /**
     * Store the validation state of the query
     */ setValid ( id , valid ) { this . _validation [ id ] = valid ; this . validationChange . next ( ! Object . keys ( this . _validation ) . some ( key => ! this . _validation [ key ] ) ) ; } /**
     * Generate a unique id for each component
     */ generateComponentId ( ) { return this . _componentId ++ ; } }