valor-software / ngx-bootstrap

Fast and reliable Bootstrap widgets in Angular (supports Ivy engine)
https://valor-software.com/ngx-bootstrap
MIT License
5.53k stars 1.69k forks source link

style typeahead results? #1557

Closed richardspruill closed 7 years ago

richardspruill commented 7 years ago

how can I style the typeahead results?

question on stackoverflow: http://stackoverflow.com/questions/41793003/style-ng2-bootstraps-typeahead-list-items

you can see in the image (on the stackoverflow question) that something is not right. Is there a way I can style the list-items the I want to? I am using a custom item template but that only lets me style the tags inside the result anchor tag. (which has a margin that I do not want).

any help would be nicely appreciated.

valorkin commented 7 years ago

I have exposed optionsListTemplate thing in v1.3.1 so you can COMPLETELY override typeahead results template ;) source code of default you can check here: https://github.com/valor-software/ng2-bootstrap/blob/development/src/typeahead/typeahead-container.component.ts#L22-L32

richardspruill commented 7 years ago

Nice! I will try that as soon as I get home :)

richardspruill commented 7 years ago

so do I add [optionsListTemplate]="customListTemplate" to my input? and then I can copy and paste those lines in the link? (matching the id of course)

This is my input :

<input
                                id="search"
                                type="search"
                                placeholder="Search..."
                                required
                                [(ngModel)]="searchInput"
                                [typeahead]="data"
                                (typeaheadOnSelect)="typeaheadOnSelect($event)"
                                (typeaheadLoading)="changeTypeaheadLoading($event)"
                                (typeaheadNoResults)="changeTypeaheadNoResults($event)"
                                typeaheadOptionsLimit="7"
                                [optionsListTemplate]="customItemTemplate"
                                typeahead="item as item.title + ' (' + item.name + ')' for item in data | filter:{title:$viewValue}"
                                name="search"
                                (ngModelChange)="search($event)"
                                class="form-control"
                                autocomplete="off"
                            >

and the template:


    <template #customItemTemplate>
        <ul class="dropdown-menu">
            <template ngFor let-match let-i="index" [ngForOf]="matches">
                <li *ngIf="match.isHeader()" class="dropdown-header" >{{match}}</li>
                <li *ngIf="!match.isHeader()" [class.active]="isActive(match)" (mouseenter)="selectActive(match)" style="width: 100%; float: none; background-color: white; color: black;">
                   <a href="#" (click)="selectMatch(match, $event)" tabindex="-1" >
                       <template [ngTemplateOutlet]="itemTemplate || bsItemTemplate"
                                                          [ngOutletContext]="{item:match.item, index:i, match:match, query:query}" style="color: black;">
                       <h5 >{{model.title || model.name}}</h5></template>
                   </a>
               </li>
           </template>
       </ul>
    </template>
valorkin commented 7 years ago

Something like that :)

richardspruill commented 7 years ago

giving me buttons as list items >.<

richardspruill commented 7 years ago

@valorkin could you please give an example with all the necessary tags(input, template etc)?

valorkin commented 7 years ago

template by link actually contain all required things

valorkin commented 7 years ago

find me in slack, to chat about it

1-0-1 commented 7 years ago

Great, this is just what I was looking for. However it seems to ignore the optionsListTemplate argument and it displays the bs4Template instead. As the OP mentions "giving me buttons as list items".

EDIT: Looks like there is a fix for this. https://codecov.io/gh/valor-software/ng2-bootstrap/compare/9cdb4e5401ef0a99e9dd4561c4b188348e02667b...6f6e83fe6c5bbeb71dd579a6f6a55eb02901efd3/diff

EDIT2: Unless I missed another fix, this still isn't working. Local template isn't being rendered.

minau87 commented 7 years ago

@1-0-1 Can confirm, same issue here, the optionsListTemplate seems to be ignored and it's instead using the bs4Template.

@valorkin This feature was added in 1.3.1, if I'm not mistaken. I assume that it has been tested and confirmed working, so maybe there's something we are missing here. Can you check what might be the reason, or alternatively, try it yourself and check if it's working for you and if that's the case, we have to take a deeper look at what the reason might be?

Oh, and also, I'm using this workaround I found somewhere.

  <script type="text/javascript">
    // temporary hack for enable bootstrap 4
    window.__theme = 'bs4';
  </script>

If I comment that out, it's switching to the bs3Template. So, that mechanism (the switchting between bs3/bs4) is working as intended, it's just that the customListTemplate, if provided, is not applied properly.

1-0-1 commented 7 years ago

I got the 1.4.0 update but this still doesn't appear to be working. Is there an example of this working someplace?

NKjoep commented 7 years ago

I've just tried this and unless there's an undocumented way to do that, It is ignoring the local template for the list.

NKjoep commented 7 years ago

Ok, I got it.

Here's my working example, I've removed unnecessary code. Look at these two myCustomItemTemplate and myCustomListTemplate, and follow them in the example.

<input [(ngModel)]="query"
        typeaheadGroupField="type"
        [typeahead]="data"
        [typeaheadItemTemplate]="myCustomItemTemplate"
        [optionsListTemplate]="myCustomListTemplate"
        placeholder="">

<ng-template #myCustomListTemplate let-matches="matches" let-itemTemplate="itemTemplate" let-query="query">
    <ng-template ngFor let-match let-i="index" [ngForOf]="matches">
        <span *ngIf="match.isHeader()">
            <!-- this is the group name -->
            {{match}} 
        </span>
        <ng-template [ngIf]="!match.isHeader()">
            <!-- itemTemplate comes from the <input> -->
            <ng-template [ngTemplateOutlet]="itemTemplate" [ngOutletContext]="{item: match.item, index: i, match: match, query: query}"></ng-template>
        </ng-template>
    </ng-template>
</ng-template>

<ng-template #myCustomItemTemplate let-model="item" let-index="index">
    <span> Model {{index}}: {{ model | json }} </span>
</ng-template>
NKjoep commented 7 years ago

So the real issue here is we are missing the isActive(match) and selectActive(match) functions since they are not scoped in the list template.

dave9111964 commented 7 years ago

I've noticed that migrating from Angular 2 to Angular 4 is fairly straight forward with no breaking changes so far. However migrating from ng2-bootstrap to ngx-bootstrap seems to introduce multiple breaking changes. Just a friendly observation.

1-0-1 commented 7 years ago

Is there a working example of this? I can get the display working with the templates, but I get no select event to fire. I've tried it with the latest released version and with 2-beta.7.

IlyaSurmay commented 7 years ago

typeaheadOptionTemplate works fine in 2.0.0-beta.8 (https://plnkr.co/edit/1TPrfJQepWWlpQ04X5ia?p=preview), so I'll close this for now. will be reopened if we have sample to reproduce

1-0-1 commented 6 years ago

That plnkr has no reference to typeaheadOptionTemplate which is what the question was about. Yes, typeaheadItemTemplate works and has an example. Please provide an example with typeaheadOptionTemplate.

flensrocker commented 6 years ago

@NKjoep regarding isActive and selectActive:

Add #typeaheadDirective="bs-typeahead" to your input, then add the following to your component:

    @ViewChild("typeaheadDirective") _typeahead: TypeaheadDirective;
    public get container(): TypeaheadContainerComponent {
        return this._typeahead._container;
    }

Then you can use container.isActive etc. in your template.

NKjoep commented 6 years ago

Oh thanks for the tip, this one is very helpful! 👍