2

I'm trying to implement a search component being able to trigger a search(term: string) function on specific children. This search function will return null if the search on the child failed or a reference to the child if succeeded.

This is so because I want to "collect" all references to the angular components that succeeded in a list, so that I could set them somehow as 'new' ContentChildren, so actually do basic filtering..

This is what I have so far:

search.component.html

<input (value)="searchterm" />
<ng-content>
    <!-- all components that implements iSearchable here -->
</ng-content>

search.component.ts

...
export class searchComponent implements OnChanges
{
    @Output('searchterm')
    public searchterm: string;

    // 1. Problem: ContentChildren does not work with interfaces?
    @ContentChildren(Isearchable)
    searchContent: QueryList<Isearchable>

    // 2. Problem: ngOnChanges will not fire when searchterm is changed
    ngOnChanges(event)
    {
        var toBeShown = [];

        // go through and let the components filter themselves
        for(let i = 0; i < this.searchContent.length; i++)
        {
            var element: Isearchable = this.searchContent[i];
            var result = element.search();

            if(result != null)  // search suceeded
                toBeShown.push(element);                
        }

        // 3. Problem: how to get them displayed ?
    }
}

Basicly I have 3 problems:

1. The first is that @ContentChildren() won't accept the (yes, imported) interface Isearchable, since '[ts] Cannot find name Isearchable'. Alternatively all Isearchable components also have a common baseclass, but this also do not work.

Currently executing the program gives me the following error: "Uncaught (in promise): Unexpected directive value 'undefined' on the View of component 'SearchComponent'"

2. The second problem is that somehow the ngOnChanges won't be fired even if I type into the input. This must be simple, do I miss something?

3. Finally, the third problem is that I do not know exactly how to make the search results (that can be of different component types) being displayed in the DOM. My hope is actually that I can somehow two-way bind to the @ContentChildren searchcontent. This would probably solve the problem, wouldn't it?

I really don't have a clue, how to continue, any help is appreciated! Thank you all!

Cheers

jlang
  • 929
  • 11
  • 32

1 Answers1

5

You can't use interfaces at this level since they only apply at design time not at runtime.

There is also an error in your code:

@Input('searchterm') // instead of @Output
public searchterm: string;

To get the list of specified components as input, you need to define a base class for your component and use this class in @ContentChildren. An additional step is required to make this work. You need to register the component itself into its providers against the parent class (with useExisting). This explanation could appear a bit "abstract" but this question could help you and will give you a concrete sample:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thank you, i totally missed that! Is there any way how to import "all html elements in between"? this could also be okay – jlang Jun 30 '16 at 15:04
  • What do you mean by "all html elements in between"? – Thierry Templier Jun 30 '16 at 15:10
  • Sorry if that was misleading. I'll give an example -> if I had I would like to get both, comp1 and 2 in this list (searchContent). – jlang Jun 30 '16 at 15:13
  • It's possible. You need to define a base class for your component and use this class in `@ContentChildren`. An additional step is required to make this work. You need to register the component itself into its providers against the parent class (with `useExisting`). This explanation could appear a bit "abstract" but this question could help you and will give you a concrete sample: http://stackoverflow.com/questions/36063627/angular2-and-class-inheritance-support. – Thierry Templier Jun 30 '16 at 15:18