andycwk
andycwk

Reputation: 846

Any examples for integrating Select2 with Angular2 Components?

I've been trying to find a demonstration/example of how to integrate Select2 into an angular 2 component.

My end goal is to use select 2 ajax features to populate the dropdown as I start typing in the select box aka https://select2.github.io/examples.html#data-ajax

So far my Google ninja powers have failed me :(

Failing examples of select2 integration... are there any other suggestions?

Upvotes: 9

Views: 12245

Answers (2)

Shahid
Shahid

Reputation: 481

When I started my hunt for Select2 multi drop-down example in Angular2, I couldn't find the kind of one I was looking for. I realized that sometimes Google ninja power doesn't work. I had to write it myself. However, I thought to share it and not let the Google ninja power down again for this. :)

plunker here to see the working demo

The core of this is to wrap the select2 in an angular component.

export class DummySelect {
  constructor(private id: string){
    $(id).select2({
      width: '100%',
      ajax: {
        url: 'https://api.github.com/search/repositories',
        datatype: 'json',
        delay: 250,
        data: function(params: any){
          return {
            q: params.term
          };
        },
        processResults: function(data:any, params: any){
          return {
            results:
              data.items.map(function(item) {
                return {
                  id: item.id,
                  text: item.full_name
                };
              }
            )};
          },
        cache: true  
      },
      placeHolder: 'Search...',
      minimumInputLength: 2 
    })
  }

  getSelectedValues(private id: string){
    return $(id).val();
  }
}

Upvotes: 3

prespic
prespic

Reputation: 1685

Let see how i got to work the select2. My purpose was init the select2 and add the _ngcontent- attribute to allow to style them via scss in my scope.

Html:

<select multiple="multiple" style="display: none;">
    <option *ngFor="#item of people" [value]="item.id">
        {{item.name}}
    </option>
</select>

Init in TypeScript on ngAfterViewInit:

ngAfterViewInit()
{
    var element = (<any>$('select')).select2().siblings('.select2-container')[0];
    var attribute = ObjectHelper.setElementContentAttribute(this.m_elementRef.nativeElement, element, true);
}

And the special magic functions to clone the _ngcontent attribute to the childs. Very usefull for lots of 3rd party libraries, where some dynamical content is generated:

public static getAngularElementTag(element: Element): string
{
    var attrs = [].filter.call(element.attributes, at => /^_nghost-/.test(at.name));
    if (attrs.length == 0)
    {
        return null;
    }
    return attrs[0].name.replace("_nghost-", "_ngcontent-");
}


public static setElementContentAttribute(hostElement: Element, targetElement: Element, setRecursive?: boolean): string
{
    var attribute = this.getAngularElementTag(hostElement);
    setRecursive = (setRecursive !== undefined) ? setRecursive : false;
    if (attribute !== null)
    {
        this._setElementContentAttribute(targetElement, setRecursive, attribute);
        return attribute;
    }
    else
    {
        return null;
    }
}

private static _setElementContentAttribute(targetElement: Element, recursive: boolean, attribute) {
    targetElement.setAttribute(attribute, '');
    if (recursive) {
        for (var i = 0; i < targetElement.childElementCount; i++) {
            this._setElementContentAttribute(<Element>targetElement.childNodes[i], recursive, attribute);
        }
    }
}

It's made just to style the input element. For dynamically added elements (selections, selector), you will probably need to catch some of the events and do the magic again.

Upvotes: 0

Related Questions