jlang
jlang

Reputation: 1057

Angular 2 - Using @ContentChildren for filtering a component's content

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

Upvotes: 2

Views: 3121

Answers (1)

Thierry Templier
Thierry Templier

Reputation: 202176

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:

Upvotes: 5

Related Questions