0

So I'm trying to build an "autocomplete" directive for a project that will query the API and display a list of results to select from. I have a component that displays a modal with a simple input box. I need to be able to type into the box to search Members, click on a member and add that to an array in the component.

Edit: The issue I'm having is that when I call this.wlAutocomplete.next(value);, it goes back into my component and makes the API call with the correct value from the input field, it doesn't return the data back to the directive to handle the response from the API there.

StackBlitz Example: https://stackblitz.com/edit/angular-11erew

The Component will track the array of selected members. I need to be able to:

  • Call my API in the Component to get the data and return to the directive
  • The directive will need to read the data and display a list below the input box (I can do the HTML here)
  • Clicking a list item in the dropdown will send that selection back to the component to handle as it needs, eg. add it to an array.

My component has a method:

queryMembers(value: string): Subscription {
  return this.memberService.query({ term: value, groupKey: this.group.groupKey })
    .subscribe((members) => {
      console.log(members);
      return this.searchMemberList = members;
    });
}

Which I'm using in the template like this:

<input (wlAutocomplete)="queryMembers($event)" class="uk-search-input" type="search" placeholder="Search...">

Here is the code for the Directive:

@Directive({
  selector: 'input[wlAutocomplete]'
})
export class AutocompleteDirective {
  modelChanged: Subject<string> = new Subject<string>();
  subscription: Subscription;
  debounce: number = 500;

  constructor() {
    this.subscription =
      this.modelChanged
        .pipe(debounceTime(this.debounce))
        .subscribe(value => {
          this.wlAutocomplete.next(value); // I need to get the data from component method passed into `wlAutocomplete`
        });
  }

  @Output() wlAutocomplete: EventEmitter<any> = new EventEmitter();

  @HostListener('input', ['$event'])
  onChange($event) {
    this.modelChanged.next($event.target.value);
  }
}
6
  • please edit your question, include a specific question, any errors, and post a minimal complete example if possible, using something like stackblitz.com Commented Sep 25, 2018 at 13:52
  • My issue is that this.wlAutocomplete.next(value); successfully goes back to the component method (queryMembers) with the string and queries the API, but I can't get the component to then return the data (a Member[]) back to the Directive to handle in there. I don't have time to put together a working example, but if needed I can look at setting one up later. Commented Sep 25, 2018 at 14:52
  • @FussinHussin Here is a StackBlitz: stackblitz.com/edit/angular-11erew. I'm struggling to figure out how to get the data from the component back into the Directive. Commented Sep 25, 2018 at 15:04
  • thanks for the example, I will look at it. just a heads up you have put people personal info in the example Commented Sep 25, 2018 at 15:24
  • So, I'm a little confused. You want the value from your directive to be received where and for what function? Commented Sep 25, 2018 at 15:36

1 Answer 1

1

Alright I think I understand what you are trying to do now, thanks for the example. You want to send values from the parent template to the directive? basically you need inputs for your directive, and bind to them in the parent.

check out this question for more

import {Directive, EventEmitter, HostListener, Input, Output} from '@angular/core';
import {Subject, Subscription} from "rxjs";
import {debounceTime} from "rxjs/operators";

@Directive({
  selector: 'input[wlAutocomplete]'
})
export class AutocompleteDirective {
  modelChanged: Subject<string> = new Subject<string>();
  subscription: Subscription;
  debounce: number = 500;

  // label and type your input, then handle it however you like
  @Input() value: any;

  constructor() {
    this.subscription =
      this.modelChanged
        .pipe(debounceTime(this.debounce))
        .subscribe(value => {
          console.log('value', value)
          console.log('directive', this.wlAutocomplete.next(value)); // I need to get the data from component method passed into `wlAutocomplete`
        });
  }

  @Output() wlAutocomplete: EventEmitter<any> = new EventEmitter();

  @HostListener('input', ['$event'])
  onChange($event) {
    console.log('directive called')
    this.modelChanged.next($event.target.value);
  }
}

template

// bind to the input in the template
    AutoComplete: <input type="text" [value]="value" (wlAutocomplete)="queryMembers($event)" />

component

import { Component } from '@angular/core';
import {Subscription} from "rxjs";
import {MemberService} from './member.service'
import {Member} from './member';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  // send value to directive 
  value: any;
  name = 'Angular';
  group: any = { groupKey: 'test' };
  debugMemberList: Member[];
  constructor(private memberService: MemberService){}

  queryMembers(value: string): Subscription {
  return this.memberService.query({ term: value, groupKey: this.group.groupKey })
    .subscribe((members) => {
      console.log('In component: ', members);
      this.value = members;
      return this.debugMemberList = members;
    });
  }
}

I'm not sure if this is the exact implementation you are looking for but hopefully that give you enough info on transferring data between the parent and directive to figure it out.

Sign up to request clarification or add additional context in comments.

1 Comment

Reading through the answer this looks like it should give me what I want, I'll give it a go later today, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.