tobias hassebrock
tobias hassebrock

Reputation: 357

Algolia Angular Instant Search: Create a custom search box template

Requested behaviour:
I would like to create an autosuggest search box using the Algolia Angular instant search feature. This search box should have an Angular Material design. Therefore I would like to use the <ais-search-box></ais-search-box> component, but I would like to add my own template.

Current State
I recreated a working Angular Instant Search component. As requested, the component delivers the correct search results if I type in a string.

issue
Now, I would like to replace the standard <ais-search-box></ais-search-box> and replace it with my custom <app-search-box></app-search-box>. I set up my code by following the Customize the UI documentation of their search box component. If I do so, I get the following error:

Member 'refine' is not callable

Is that the reason why my component does not work anymore? If so, how can I fix it?

my not working custom search-box component

import { Component, Inject, forwardRef } from '@angular/core';
import { BaseWidget, NgAisInstantSearch } from 'angular-instantsearch';
import { connectSearchBox } from 'instantsearch.js/es/connectors';

// (keyup)="this.state.refine(input.value)" throws the error
@Component({
  selector: 'app-search-box',
  template: `
<input
  type="text"
  #input
  (keyup)="this.state.refine(input.value)"
  [value]="this.state.query"
/>
`
})
export class SearchBox extends BaseWidget {
  public state: {
     query: string;
     refine: Function;
     clear: Function;
     isSearchStalled: boolean;
     widgetParams: object;
  };
  constructor(
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchParent
  ) {
    super('SearchBox');
    this.createWidget(connectSearchBox, {
      // instance options
    });
  }
}

my working search component

import { Component } from '@angular/core';
import { environment } from 'src/environments/environment';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent {
  searchConfig = {
    ...environment.algolia,
    indexName: 'ideas'
  };

  showResults = false;

  constructor() { }

  searchChanged(query) {
    if (query.length) {
      this.showResults = true;
    } else {
      this.showResults = false;
    }
  }
}

my working html template

<ais-instantsearch [config]="searchConfig">
  <!---working ais search box component-->
  <ais-search-box (change)="searchChanged($event)"></ais-search-box>

    <!---should be replaced by my custom search-box component.-->
    <!--<app-search-box (change)="searchChanged($event)"></app-search-box>-->
  
    <ais-hits *ngIf="showResults">
        <ng-template let-hits="hits">
            <div *ngFor="let hit of hits">  
                <div class="bio">
                    {{ hit.ideaText }}
                </div>
            </div>
        </ng-template>
    </ais-hits>
  </ais-instantsearch>

Upvotes: 2

Views: 1465

Answers (1)

Burlon23
Burlon23

Reputation: 107

check that with Angular Material

HTML

<mat-form-field class="col-sm-10" (keydown)="keyDownFunction($event)">
      <input matInput type="search" placeholder="Buscar:" name="search" [(ngModel)]="searchbox"
        (keyup)="onQuery($event)" (ngModelChange)="updatedVal($event)">
    </mat-form-field>

TS

public searchbox;
private query: string = "";

//Enter KEY
    keyDownFunction($event) {

        const text = this.query;

        if ($event.keyCode == 13) {
            this._router.navigate([`/search/${text.replace(/\s+/g, '_')}`])
        }
    }

//Button KEY
    BtnFunction($event) {

        const text = this.query;

        if ($event) {
            this._router.navigate([`/search/${text.replace(/\s+/g, '_')}`])
        }
    }

// Algolia KEY
    onQuery($event) {
        this.query = $event.target.value;
    }

Upvotes: -1

Related Questions