{"id":6020,"date":"2017-09-16T18:57:18","date_gmt":"2017-09-16T16:57:18","guid":{"rendered":"https:\/\/www.tomislavstankovic.com\/blog\/?p=6020"},"modified":"2019-01-05T19:52:58","modified_gmt":"2019-01-05T17:52:58","slug":"ionic-3-autocomplete-select-search","status":"publish","type":"post","link":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/","title":{"rendered":"Ionic 3 &#8211; select, search i autocomplete komponenta"},"content":{"rendered":"<p>Iako sam ve\u0107 objavio blog post na temu <a href=\"https:\/\/www.tomislavstankovic.com\/blog\/ionic3-autocomplete\/\" target=\"_blank\"><em>Ionic 3 autocomplete<\/em> funkcionalnosti<\/a> mislim da \u0107e vam se primjer iz ovog blog posta jo\u0161 vi\u0161e svidjeti. Cijela se funkcionalnost temelji na pro\u0161irivanju mogu\u0107nosti ve\u0107 postoje\u0107e <a href=\"https:\/\/ionicframework.com\/docs\/api\/components\/select\/Select\/\" target=\"_blank\"><em>Ionic Select<\/em> komponente<\/a>. <\/p>\n<h2>Postavljanje aplikacije<\/h2>\n<p>Za po\u010detak je potrebno kreirati <a href=\"https:\/\/www.tomislavstankovic.com\/blog\/stigao-je-ionic-3\/\" target=\"_blank\">novi <em>Ionic<\/em> projekt<\/a><\/p>\n<pre class=\"lang:sh decode:true \" >$ ionic start Ionic3SelectSearchAutocomplete blank\r\n$ cd Ionic3SelectSearchAutocomplete<\/pre>\n<h2>Izrada select komponente<\/h2>\n<p>Komponentu mo\u017eete kreirati sljede\u0107om naredbom:<\/p>\n<pre class=\"lang:sh decode:true \" >$ ionic generate component select-search<\/pre>\n<p>Struktura datoteka sada izgleda ovako:<\/p>\n<pre class=\"lang:default mark:4-12 decode:true \" >--src\r\n - app\r\n - assets\r\n - components\r\n  - select-search\r\n   - select-search-module.ts\r\n   - select-search-page.html\r\n   - select-search-page.scss\r\n   - select-search-page.ts\r\n   - select-search.html\r\n   - select-search.scss\r\n   - select-search.ts\r\n - pages\r\n - theme\r\n - ...<\/pre>\n<p>Sadr\u017eaj datoteka mo\u017eete vidjeti u nastavku.<\/p>\n<p><strong>select-search-module.ts<\/strong><\/p>\n<p>Ovdje definiramo modul koji \u0107e <em>Ionic<\/em> aplikaciji re\u0107i od \u010dega se sastoji na\u0161a <em>Ionic<\/em> komponenta te kako ju aplikacija prilikom pokretanja treba interpretirati.<\/p>\n<pre class=\"lang:js decode:true \" title=\"select-search-module.ts\" >import { NgModule } from '@angular\/core';\r\nimport { IonicPageModule } from 'ionic-angular';\r\nimport { SelectSearch } from '.\/select-search';\r\nimport { SelectSearchPage } from '.\/select-search-page';\r\n\r\n@NgModule({\r\n    declarations: [\r\n        SelectSearch,\r\n        SelectSearchPage\r\n    ],\r\n    imports: [\r\n        IonicPageModule.forChild(SelectSearch),\r\n        IonicPageModule.forChild(SelectSearchPage)\r\n    ],\r\n    exports: [\r\n        SelectSearch,\r\n        SelectSearchPage\r\n    ],\r\n    entryComponents: [\r\n        SelectSearch,\r\n        SelectSearchPage\r\n    ]\r\n})\r\nexport class SelectSearchModule { }<\/pre>\n<p><strong>select-search-page.html<\/strong><\/p>\n<pre class=\"lang:xhtml decode:true \" title=\"select-search-page.html\" >&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n        &lt;ion-title&gt;{{selectComponent.title}}&lt;\/ion-title&gt;\r\n    &lt;\/ion-navbar&gt;\r\n    &lt;ion-toolbar *ngIf=\"selectComponent.canSearch\"&gt;\r\n        &lt;ion-searchbar\r\n            #searchbarComponent\r\n            [(ngModel)]=\"selectComponent.filterText\"\r\n            (ionInput)=\"filterItems()\"\r\n            [placeholder]=\"selectComponent.searchPlaceholder || 'Search'\"&gt;\r\n        &lt;\/ion-searchbar&gt;\r\n    &lt;\/ion-toolbar&gt;\r\n&lt;\/ion-header&gt;\r\n&lt;ion-content&gt;\r\n    &lt;div class=\"select-search-spinner\" *ngIf=\"selectComponent.isSearching\"&gt;\r\n        &lt;div class=\"select-search-spinner-background\"&gt;&lt;\/div&gt;\r\n        &lt;ion-spinner&gt;&lt;\/ion-spinner&gt;\r\n    &lt;\/div&gt;\r\n    &lt;ion-list no-margin *ngIf=\"filteredItems.length\"&gt;\r\n        &lt;button ion-item detail-none *ngFor=\"let item of filteredItems\" (click)=\"select(item)\"&gt;\r\n            &lt;ion-icon\r\n                [name]=\"isItemSelected(item) ? 'checkmark-circle' : 'radio-button-off'\"\r\n                [color]=\"isItemSelected(item) ? 'primary' : 'daek'\"\r\n                item-left&gt;\r\n            &lt;\/ion-icon&gt;\r\n            &lt;h2&gt;{{selectComponent.formatItem(item)}}&lt;\/h2&gt;\r\n        &lt;\/button&gt;\r\n    &lt;\/ion-list&gt;\r\n    &lt;div *ngIf=\"!filteredItems.length\" margin&gt;No items found.&lt;\/div&gt;\r\n&lt;\/ion-content&gt;\r\n&lt;ion-footer *ngIf=\"selectComponent.canReset || selectComponent.multiple\"&gt;\r\n    &lt;ion-toolbar padding&gt;\r\n        &lt;ion-row&gt;\r\n            &lt;ion-col no-padding *ngIf=\"selectComponent.canReset\"\r\n                [attr.col-6]=\"selectComponent.canReset &amp;&amp; selectComponent.multiple ? '' : null\"\r\n                [attr.col-12]=\"selectComponent.canReset &amp;&amp; !selectComponent.multiple ? '' : null\"&gt;\r\n                &lt;button ion-button full no-margin (click)=\"reset()\" [disabled]=\"!selectedItems.length\"&gt;\r\n                    Clear\r\n                &lt;\/button&gt;\r\n            &lt;\/ion-col&gt;\r\n            &lt;ion-col no-padding *ngIf=\"selectComponent.multiple\"\r\n                [attr.col-6]=\"selectComponent.canReset &amp;&amp; selectComponent.multiple ? '' : null\"\r\n                [attr.col-12]=\"!selectComponent.canReset &amp;&amp; selectComponent.multiple ? '' : null\"&gt;\r\n                &lt;button ion-button full no-margin (click)=\"ok()\"&gt;\r\n                    OK\r\n                &lt;\/button&gt;\r\n            &lt;\/ion-col&gt;\r\n        &lt;\/ion-row&gt;\r\n    &lt;\/ion-toolbar&gt;\r\n&lt;\/ion-footer&gt;<\/pre>\n<p><strong>select-search-page.scss<\/strong><\/p>\n<pre class=\"lang:css decode:true \" title=\"select-search-page.scss\" >.select-search-page {\r\n    &amp;.select-search-page-can-reset.select-search-page-multiple {\r\n        .footer .col:first-child {\r\n            padding-right: $content-margin \/ 2;\r\n        }\r\n        \r\n        .footer .col:last-child {\r\n            padding-left: $content-margin \/ 2;\r\n        }\r\n    }\r\n}<\/pre>\n<p><strong>select-search-page.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \" title=\"select-search-page.ts\" >import { Component, ViewChild } from '@angular\/core';\r\nimport { NavParams, NavController, Searchbar } from 'ionic-angular';\r\nimport { SelectSearch } from '.\/select-search';\r\n\r\n@Component({\r\n    selector: 'select-search-page',\r\n    templateUrl: 'select-search-page.html',\r\n    host: {\r\n        'class': 'select-search-page',\r\n        '[class.select-search-page-can-reset]': 'selectComponent.canReset',\r\n        '[class.select-search-page-multiple]': 'selectComponent.multiple'\r\n    }\r\n})\r\nexport class SelectSearchPage {\r\n    selectComponent: SelectSearch;\r\n    filteredItems: any[];\r\n    selectedItems: any[] = [];\r\n    navController: NavController;\r\n    @ViewChild('searchbarComponent') searchbarComponent: Searchbar;\r\n\r\n    constructor(private navParams: NavParams) {\r\n        this.selectComponent = navParams.get('selectComponent');\r\n        this.navController = navParams.get('navController');\r\n        this.filteredItems = this.selectComponent.items;\r\n        this.filterItems();\r\n\r\n        if (this.selectComponent.value) {\r\n            if (this.selectComponent.multiple) {\r\n                this.selectComponent.value.forEach(item =&gt; {\r\n                    this.selectedItems.push(item);\r\n                });\r\n            } else {\r\n                this.selectedItems.push(this.selectComponent.value);\r\n            }\r\n        }\r\n    }\r\n\r\n    ngAfterViewInit() {\r\n        if (this.searchbarComponent) {\r\n            \/\/ Focus after a delay because focus doesn't work without it.\r\n            setTimeout(() =&gt; {\r\n                this.searchbarComponent.setFocus();\r\n            }, 1000);\r\n        }\r\n    }\r\n\r\n    isItemSelected(item: any) {\r\n        return this.selectedItems.find(selectedItem =&gt; {\r\n            if (this.selectComponent.itemValueField) {\r\n                return item[this.selectComponent.itemValueField] === selectedItem[this.selectComponent.itemValueField];\r\n            }\r\n\r\n            return item === selectedItem;\r\n        }) !== undefined;\r\n    }\r\n\r\n    deleteSelectedItem(item: any) {\r\n        let itemToDeleteIndex;\r\n\r\n        this.selectedItems.forEach((selectedItem, itemIndex) =&gt; {\r\n            if (this.selectComponent.itemValueField) {\r\n                if (item[this.selectComponent.itemValueField] === selectedItem[this.selectComponent.itemValueField]) {\r\n                    itemToDeleteIndex = itemIndex;\r\n                }\r\n            } else if (item === selectedItem) {\r\n                itemToDeleteIndex = itemIndex;\r\n            }\r\n        });\r\n\r\n        this.selectedItems.splice(itemToDeleteIndex, 1);\r\n    }\r\n\r\n    addSelectedItem(item: any) {\r\n        this.selectedItems.push(item);\r\n    }\r\n\r\n    select(item: any) {\r\n        if (this.selectComponent.multiple) {\r\n            if (this.isItemSelected(item)) {\r\n                this.deleteSelectedItem(item);\r\n            } else {\r\n                this.addSelectedItem(item);\r\n            }\r\n        } else {\r\n            if (!this.isItemSelected(item)) {\r\n                this.selectedItems = [];\r\n                this.addSelectedItem(item);\r\n                this.selectComponent.select(item);\r\n            }\r\n\r\n            this.close();\r\n        }\r\n    }\r\n\r\n    ok() {\r\n        this.selectComponent.select(this.selectedItems.length ? this.selectedItems : null);\r\n        this.close();\r\n    }\r\n\r\n    close() {\r\n        \/\/ Focused input interferes with the animation.\r\n        \/\/ Blur it first, wait a bit and then close the page.\r\n        if (this.searchbarComponent) {\r\n            this.searchbarComponent._fireBlur();\r\n        }\r\n\r\n        setTimeout(() =&gt; {\r\n            this.navController.pop();\r\n\r\n            if (!this.selectComponent.hasSearchEvent) {\r\n                this.selectComponent.filterText = '';\r\n            }\r\n        });\r\n    }\r\n\r\n    reset() {\r\n        this.navController.pop();\r\n        this.selectComponent.reset();\r\n    }\r\n\r\n    filterItems() {\r\n        if (this.selectComponent.hasSearchEvent) {\r\n            if (this.selectComponent.isNullOrWhiteSpace(this.selectComponent.filterText)) {\r\n                this.selectComponent.items = [];\r\n            } else {\r\n                \/\/ Delegate filtering to the event.\r\n                this.selectComponent.emitSearch();\r\n            }\r\n        } else {\r\n            \/\/ Default filtering.\r\n            if (!this.selectComponent.filterText || !this.selectComponent.filterText.trim()) {\r\n                this.filteredItems = this.selectComponent.items;\r\n                return;\r\n            }\r\n\r\n            let filterText = this.selectComponent.filterText.trim().toLowerCase();\r\n\r\n            this.filteredItems = this.selectComponent.items.filter(item =&gt; {\r\n                return item[this.selectComponent.itemTextField].toLowerCase().indexOf(filterText) !== -1;\r\n            });\r\n        }\r\n    }\r\n}<\/pre>\n<p><strong>select-search.html<\/strong><\/p>\n<pre class=\"lang:xhtml decode:true \" title=\"select-search.html\" >&lt;div class=\"select-search-label\"&gt;{{title}}&lt;\/div&gt;\r\n&lt;div class=\"select-search-value\"&gt;{{formatValue()}}&lt;\/div&gt;\r\n&lt;div class=\"select-search-icon\"&gt;\r\n    &lt;div class=\"select-search-icon-inner\"&gt;&lt;\/div&gt;\r\n&lt;\/div&gt;\r\n&lt;button aria-haspopup=\"true\" ion-button=\"item-cover\" class=\"item-cover\"&gt;&lt;\/button&gt;<\/pre>\n<p><strong>select-search.scss<\/strong><\/p>\n<pre class=\"lang:css decode:true \" title=\"select-search.scss\" >.item-select-search {\r\n    .label {\r\n        margin-right: 0;\r\n    }\r\n}\r\n\r\n.select-search {\r\n    display: flex;\r\n\r\n    &amp;-label {\r\n        flex: 1;\r\n        text-overflow: ellipsis;\r\n        overflow: hidden;\r\n    }\r\n\r\n    &amp;-value {\r\n        max-width: 45%;\r\n        text-overflow: ellipsis;\r\n        overflow: hidden;\r\n    }\r\n\r\n    &amp;-icon {\r\n        position: relative;\r\n        width: 20px;\r\n    }\r\n\r\n    &amp;-icon-inner {\r\n        position: absolute;\r\n        top: 50%;\r\n        left: 5px;\r\n        border-top: 5px solid;\r\n        border-right: 5px solid transparent;\r\n        border-left: 5px solid transparent;\r\n        pointer-events: none;\r\n    }\r\n\r\n    &amp;-ios {\r\n        .select-search-icon {\r\n            height: 18px;\r\n        }\r\n\r\n        .select-search-icon-inner {\r\n            margin-top: -2px;\r\n            color: $select-ios-icon-color;\r\n        }\r\n\r\n        .select-search-value {\r\n            padding-left: $select-ios-padding-left;\r\n        }\r\n    }\r\n\r\n    &amp;-md {\r\n        .select-search-icon {\r\n            height: 19px;\r\n        }\r\n\r\n        .select-search-icon-inner {\r\n            margin-top: -3px;\r\n            color: $select-md-icon-color;\r\n        }\r\n\r\n        .select-search-value {\r\n            padding-left: $select-md-padding-left;\r\n        }\r\n\r\n        .select-search-label {\r\n            color: $select-md-placeholder-color;\r\n        }\r\n    }\r\n\r\n    &amp;-spinner {\r\n        &amp;-background {\r\n            top: 0;\r\n            bottom: 0;\r\n            left: 0;\r\n            right: 0;\r\n            position: absolute;\r\n            background-color: #000;\r\n            z-index: 100;\r\n            opacity: 0.05;\r\n        }\r\n\r\n        ion-spinner {\r\n            position: absolute;\r\n            top: 50%;\r\n            left: 50%;\r\n            z-index: 10;\r\n            margin-top: -14px;\r\n            margin-left: -14px;\r\n        }\r\n    }\r\n}<\/pre>\n<p><strong>select-search.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \" title=\"select-search.ts\" >import { Component, Input, Output, EventEmitter, Optional, OnDestroy, forwardRef, HostListener, OnChanges, SimpleChanges } from '@angular\/core';\r\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular\/forms';\r\nimport { Item, Form, NavController, Platform } from 'ionic-angular';\r\nimport { SelectSearchPage } from '.\/select-search-page';\r\n\r\n@Component({\r\n    selector: 'select-search',\r\n    templateUrl: 'select-search.html',\r\n    providers: [{\r\n        provide: NG_VALUE_ACCESSOR,\r\n        useExisting: forwardRef(() =&gt; SelectSearch),\r\n        multi: true\r\n    }],\r\n    host: {\r\n        'class': 'select-search',\r\n        '[class.select-search-ios]': 'isIos',\r\n        '[class.select-search-md]': 'isMd',\r\n        '[class.select-search-can-reset]': 'canReset'\r\n    }\r\n})\r\nexport class SelectSearch implements ControlValueAccessor, OnDestroy, OnChanges {\r\n    private _items: any[] = [];\r\n    private isIos: boolean;\r\n    private isMd: boolean;\r\n    filterText = '';\r\n    value: any = null;\r\n    hasSearchEvent: boolean;\r\n    get items(): any[] {\r\n        return this._items;\r\n    }\r\n    @Input('items')\r\n    set items(items: any[]) {\r\n        \/\/ The original reference of the array should be preserved to keep two-way data binding working between SelectSearchable and SelectSearchablePage.\r\n        this._items.splice(0, this._items.length);\r\n\r\n        \/\/ Add new items to the array.\r\n        Array.prototype.push.apply(this._items, items);\r\n    }\r\n    @Input() isSearching: boolean;\r\n    @Input() itemValueField: string;\r\n    @Input() itemTextField: string;\r\n    @Input() canSearch = false;\r\n    @Input() canReset = false;\r\n    @Input() title: string;\r\n    @Input() searchPlaceholder: string = '...';\r\n    @Output() onChange: EventEmitter&lt;any&gt; = new EventEmitter();\r\n    @Output() onSearch: EventEmitter&lt;any&gt; = new EventEmitter();\r\n    @Input() itemTemplate: Function;\r\n    @Input() multiple: boolean;\r\n\r\n    constructor(private navController: NavController, private ionForm: Form, private platform: Platform, @Optional() private ionItem: Item) { }\r\n\r\n    isNullOrWhiteSpace(value: any): boolean {\r\n        if (value === null || value === undefined) {\r\n            return true;\r\n        }\r\n\r\n        \/\/ Convert value to string in case if it's not.\r\n        return value.toString().replace(\/\\s\/g, '').length &lt; 1;\r\n    }\r\n\r\n    ngOnInit() {\r\n        this.isIos = this.platform.is('ios');\r\n        this.isMd = this.platform.is('android');\r\n        this.hasSearchEvent = this.onSearch.observers.length &gt; 0;\r\n        this.ionForm.register(this);\r\n\r\n        if (this.ionItem) {\r\n            this.ionItem.setElementClass('item-select-search', true);\r\n        }\r\n    }\r\n\r\n    initFocus() { }\r\n\r\n    @HostListener('click', ['$event'])\r\n    _click(event: UIEvent) {\r\n        if (event.detail === 0) {\r\n            \/\/ Don't continue if the click event came from a form submit.\r\n            return;\r\n        }\r\n\r\n        event.preventDefault();\r\n        event.stopPropagation();\r\n        this.open();\r\n    }\r\n\r\n    select(selectedItem: any) {\r\n        this.value = selectedItem;\r\n        this.emitChange();\r\n    }\r\n\r\n    emitChange() {\r\n        this.propagateChange(this.value);\r\n        this.onChange.emit({\r\n            component: this,\r\n            value: this.value\r\n        });\r\n    }\r\n\r\n    emitSearch() {\r\n        this.onSearch.emit({\r\n            component: this,\r\n            text: this.filterText\r\n        });\r\n    }\r\n\r\n    open() {\r\n        this.navController.push(SelectSearchPage, {\r\n            selectComponent: this,\r\n            navController: this.navController\r\n        });\r\n    }\r\n\r\n    reset() {\r\n        this.setValue(null);\r\n        this.emitChange();\r\n    }\r\n\r\n    formatItem(value: any): string {\r\n        if (this.itemTemplate) {\r\n            return this.itemTemplate(value);\r\n        }\r\n\r\n        return value ? value[this.itemTextField] : null;\r\n    }\r\n\r\n    formatValue(): string {\r\n        if (!this.value) {\r\n            return null;\r\n        }\r\n\r\n        if (this.multiple) {\r\n            return this.value.map(item =&gt; this.formatItem(item)).join(', ');\r\n        } else {\r\n            return this.formatItem(this.value);\r\n        }\r\n    }\r\n\r\n    private propagateChange = (_: any) =&gt; { }\r\n\r\n    writeValue(value: any) {\r\n        this.setValue(value);\r\n    }\r\n\r\n    registerOnChange(fn: any): void {\r\n        this.propagateChange = fn;\r\n    }\r\n\r\n    registerOnTouched(fn: any) { }\r\n\r\n    setDisabledState(isDisabled: boolean) { }\r\n\r\n    ngOnDestroy() {\r\n        this.ionForm.deregister(this);\r\n    }\r\n\r\n    setValue(value: any) {\r\n        this.value = value;\r\n\r\n        \/\/ Get an item from the list for value.\r\n        \/\/ We need this in case value contains only id, which is not sufficient for template rendering.\r\n        if (this.value &amp;&amp; !this.isNullOrWhiteSpace(this.value[this.itemValueField])) {\r\n            let selectedItem = this.items.find(item =&gt; {\r\n                return item[this.itemValueField] === this.value[this.itemValueField];\r\n            });\r\n\r\n            if (selectedItem) {\r\n                this.value = selectedItem;\r\n            }\r\n        }\r\n    }\r\n\r\n    ngOnChanges(changes: SimpleChanges) {\r\n        if (changes['items'] &amp;&amp; this.items.length &gt; 0) {\r\n            this.setValue(this.value);\r\n        }\r\n    }\r\n}<\/pre>\n<p>\u0160to se komponente ti\u010de gore navedene datoteke su sve \u0161to vam treba. Za ne\u0161to vi\u0161e posjetite <a href=\"https:\/\/github.com\/eakoriakin\/ionic-select-searchable\" target=\"_blank\">https:\/\/github.com\/eakoriakin\/ionic-select-searchable<\/a><\/p>\n<h2>Kreiranje klase<\/h2>\n<p>Nakon \u0161to smo kreirali komponentu mo\u017eemo kreirati i klasu koja \u0107e se nalaziti u posebnoj datoteci. Takva vrsta odvajanja olak\u0161ava kasnije odr\u017eavanje aplikacija.<\/p>\n<p><strong>country.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true   \" title=\"country.ts\" >export class Country {\r\n    public id: number;\r\n    public name: string;\r\n    public population: number;\r\n}<\/pre>\n<p><strong>types.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true   \" title=\"types.ts\" >export * from '.\/country';<\/pre>\n<p>Struktura datoteka sada izgleda ovako<\/p>\n<pre class=\"lang:default mark:15-17 decode:true \" >--src\r\n - app\r\n - assets\r\n - components\r\n  - select-search\r\n   - select-search-module.ts\r\n   - select-search-page.html\r\n   - select-search-page.scss\r\n   - select-search-page.ts\r\n   - select-search.html\r\n   - select-search.scss\r\n   - select-search.ts\r\n - pages\r\n - theme\r\n - types\r\n  - country.ts\r\n  - types.ts\r\n - ...<\/pre>\n<h2>Kori\u0161tenje funkcionalnosti<\/h2>\n<p>Imamo komponentu, imamo klasu i sada napokon mo\u017eemo ne\u0161to od svega toga konkretno i napraviti. Ako vam sve napravljeno do sada nije bilo poznato mo\u017eete odahnuti jer se sada fokusiramo na <strong>home.ts<\/strong> i <strong>home.html<\/strong> datoteke jer ondje \u0107emo koristiti ranije kreiranu komponentu.<\/p>\n<p><strong>home.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \" title=\"home.ts\" >import { Component } from '@angular\/core';\r\n\r\nimport { FormBuilder, FormGroup, FormControl, Validators } from '@angular\/forms';\r\nimport { SelectSearch } from '..\/..\/components\/select-search\/select-search';\r\nimport { Country } from '..\/..\/types\/types';\r\n\r\n@Component({\r\n  selector: 'page-home',\r\n  templateUrl: 'home.html'\r\n})\r\nexport class HomePage {\r\n\r\n  countries: Country[];\r\n    country1: Country;\r\n    country2: Country;\r\n    country3: Country;\r\n    country4: Country;\r\n    country5: Country;\r\n    country6: Country;\r\n    country7: Country;\r\n    form: FormGroup;\r\n    country8Control: FormControl;\r\n\r\n  constructor(private _formBuilder: FormBuilder) {\r\n\r\n    this.countries = this.getCountries();\r\n        this.country2 = this.countries[4];\r\n        this.country7 = this.countries[4];\r\n        this.country8Control = _formBuilder.control(this.countries[4], Validators.required);\r\n        this.form = _formBuilder.group({\r\n            country8: this.country8Control\r\n        });\r\n\r\n  }\r\n\r\n  getCountries(): Country[] {\r\n        return [\r\n            { id: 0, name: 'Afghanistan', population: 27657145 },\r\n            { id: 1, name: 'Albania', population: 2886026 },\r\n            { id: 2, name: 'Austria', population: 8725931 },\r\n            { id: 3, name: 'Bosnia and Herzegovina', population: 3531159 },\r\n            { id: 4, name: 'Croatia', population: 4190669 },\r\n            { id: 5, name: 'France', population: 66710000 },\r\n            { id: 6, name: 'Hungary', population: 9823000 },\r\n            { id: 7, name: 'Indonesia', population: 258705000 },\r\n            { id: 8, name: 'Liechtenstein', population: 37623 },\r\n            { id: 9, name: 'Mexico', population: 122273473 },\r\n            { id: 10, name: 'San Marino', population: 33005 }\r\n        ];\r\n    }\r\n\r\n    searchCountries(event: { component: SelectSearch, text: string }) {\r\n        let text = (event.text || '').trim().toLowerCase();\r\n\r\n        if (!text) {\r\n            event.component.items = [];\r\n            return;\r\n        } else if (event.text.length &lt; 3) {\r\n            return;\r\n        }\r\n\r\n        event.component.isSearching = true;\r\n\r\n        \/\/ Simulate AJAX.\r\n        setTimeout(() =&gt; {\r\n            event.component.items = this.getCountries().filter(country =&gt; {\r\n                return country.name.toLowerCase().indexOf(text) !== -1\r\n            });\r\n\r\n            event.component.isSearching = false;\r\n        }, 2000);\r\n    }\r\n\r\n    countryTemplate(country: Country) {\r\n        return `${country.name}, ${country.population}`;\r\n    }\r\n\r\n    countryChange(event: { component: SelectSearch, value: any }) {\r\n        console.log('value:', event.value);\r\n    }\r\n\r\n    reset() {\r\n        this.country8Control.reset();\r\n    }\r\n\r\n}<\/pre>\n<p><strong>home.html<\/strong><\/p>\n<pre class=\"lang:xhtml decode:true \" title=\"home.html\" >&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n        &lt;ion-title&gt;Ionic: Select, search & autocomplete&lt;\/ion-title&gt;\r\n    &lt;\/ion-navbar&gt;\r\n&lt;\/ion-header&gt;\r\n&lt;ion-content&gt;\r\n     &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            Simple Select\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country1\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt; \r\n     &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            With preselected value\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country2\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt; \r\n     &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            With Search\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country3\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                [canSearch]=\"true\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt; \r\n     &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            With Async Search (AJAX)\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country4\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                [canSearch]=\"true\"\r\n                searchPlaceholder=\"...\"\r\n                (onSearch)=\"searchCountries($event)\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt; \r\n     &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            With a custom template for items\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country5\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [itemTemplate]=\"countryTemplate\"\r\n                [items]=\"countries\"\r\n                [canSearch]=\"true\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt; \r\n    &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            Multiple selection\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country6\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                [canSearch]=\"true\"\r\n                [multiple]=\"true\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt;\r\n    &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            With \"Clear\" button\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country7\"\r\n                title=\"Country\"\r\n                itemValueField=\"id\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                (onChange)=\"countryChange($event)\"\r\n                [canReset]=\"true\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt;\r\n    &lt;form [formGroup]=\"form\"&gt;\r\n        &lt;ion-list&gt;\r\n            &lt;ion-list-header&gt;\r\n                Using together with Angular 2 Validators\r\n            &lt;\/ion-list-header&gt;\r\n            &lt;ion-item&gt;\r\n                &lt;select-search\r\n                    formControlName=\"country8\"\r\n                    title=\"Country\"\r\n                    itemValueField=\"id\"\r\n                    itemTextField=\"name\"\r\n                    [items]=\"countries\"\r\n                    [canSearch]=\"true\"\r\n                    (onChange)=\"countryChange($event)\"&gt;\r\n                &lt;\/select-search&gt;\r\n                &lt;button ion-button item-right (click)=\"reset()\" [disabled]=\"!form.valid\"&gt;Reset&lt;\/button&gt;\r\n            &lt;\/ion-item&gt;\r\n            &lt;ion-item&gt;\r\n                &lt;p&gt;Is valid: {{form.valid}}&lt;\/p&gt;\r\n            &lt;\/ion-item&gt;\r\n        &lt;\/ion-list&gt;\r\n    &lt;\/form&gt; \r\n&lt;\/ion-content&gt;<\/pre>\n<p>Na kraju to izgleda ovako<\/p>\n<p><a href=\"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.gif\" alt=\"Ionic 3 - select, search i autocomplete komponenta\" width=\"917\" height=\"1098\" class=\"aligncenter size-full wp-image-6042\" \/><\/a><\/p>\n<h2>Prikaz podataka direktno s API-ja<\/h2>\n<p>Ovdje \u0107u koristiti <a href=\"https:\/\/restcountries.eu\/rest\/v2\/all\" target=\"_blank\">https:\/\/restcountries.eu\/rest\/v2\/all<\/a> <em>API<\/em>. Ovaj sam <a href=\"https:\/\/www.tomislavstankovic.com\/blog\/ionic3-autocomplete\/\" target=\"_blank\">API koristio u jednom od prethodnih blog postova<\/a>.<\/p>\n<p>Prvo je potrebno kreirati  <span class=\"lang:js decode:true  crayon-inline\">ApiProvider<\/span> naredbom:<\/p>\n<pre class=\"lang:sh decode:true\">$ ionic generate provider ApiProvider<\/pre>\n<p>Sadr\u017eaj izgleda ovako:<\/p>\n<pre class=\"lang:js decode:true \" title=\"api.ts\" >import { Injectable } from '@angular\/core';\r\nimport { Http } from '@angular\/http';\r\nimport 'rxjs\/add\/operator\/map';\r\n\r\n@Injectable()\r\nexport class ApiProvider {\r\n\r\n  constructor(public _http: Http) {\r\n    console.log('Hello ApiProvider Provider');\r\n  }\r\n\r\n   loadData(){\r\n    return this._http.get('https:\/\/restcountries.eu\/rest\/v2\/all')\r\n      .map(res =&gt; res.json());\r\n  }\r\n\r\n}<\/pre>\n<p>I sada se opet vra\u0107amo datotekama <strong>home.html<\/strong> i <strong>home.ts<\/strong> koje \u0107u za potrebe ovog primjera pojednostaviti.<\/p>\n<pre class=\"lang:xhtml decode:true \" title=\"home.html\" >&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n        &lt;ion-title&gt;Ionic: Select, search &amp; autocomplete&lt;\/ion-title&gt;\r\n    &lt;\/ion-navbar&gt;\r\n&lt;\/ion-header&gt;\r\n&lt;ion-content&gt;\r\n    &lt;ion-list&gt;\r\n        &lt;ion-list-header&gt;\r\n            Multiple selection\r\n        &lt;\/ion-list-header&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;select-search\r\n                [(ngModel)]=\"country\"\r\n                title=\"Country\"\r\n                itemValueField=\"population\"\r\n                itemTextField=\"name\"\r\n                [items]=\"countries\"\r\n                [canSearch]=\"true\"\r\n                [multiple]=\"true\"\r\n                (onChange)=\"countryChange($event)\"&gt;\r\n            &lt;\/select-search&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt;\r\n&lt;\/ion-content&gt;<\/pre>\n<p>Funkcionalnost se sastoji od tri glavna dijela. Prvi dohva\u0107a sve podatke s API-ja, drugi puni novi niz samo sa podacima koje \u017eelimo koristiti u aplikaciji i tre\u0107i se ti\u010de odabira vrijednosti u komponenti na klijentskoj strani.<\/p>\n<pre class=\"lang:js decode:true \" title=\"home.ts\" >import { Component } from '@angular\/core';\r\n\r\nimport { SelectSearch } from '..\/..\/components\/select-search\/select-search';\r\nimport { Country } from '..\/..\/types\/types';\r\n\r\nimport { ApiProvider } from \"..\/..\/providers\/api\/api\";\r\n\r\n@Component({\r\n  selector: 'page-home',\r\n  templateUrl: 'home.html',\r\n  providers: [ApiProvider]\r\n})\r\nexport class HomePage {\r\n\r\n    countries: Country[];\r\n    country: Country;\r\n\r\n    countryOptions:any;\r\n\r\n  constructor(public _apiProvider: ApiProvider) {\r\n\r\n  }\r\n\r\n   ionViewDidLoad() {\r\n    this.getCountries();\r\n  }\r\n\r\n     getCountries(){\r\n     this._apiProvider.loadData().subscribe(res =&gt; {\r\n     this.countryOptions = res;\r\n     console.log(this.countryOptions);\r\n\r\n          let myCountries = [];\r\n            if(this.countryOptions.length &gt; 0) {\r\n                for(let i = 0; i &lt; this.countryOptions.length; i++) {\r\n                    myCountries.push({\r\n                        id: this.countryOptions[i].alpha2Code,\r\n                        population: this.countryOptions[i].population,\r\n                        name: this.countryOptions[i].name\r\n                    });\r\n                }\r\n            } \r\n\r\n         this.countries = this.passingFunction(myCountries);\r\n    \r\n    });\r\n  } \r\n\r\n   passingFunction(data:any): Country[]{\r\n    return data\r\n   }\r\n\r\n    countryChange(event: { component: SelectSearch, value: any }) {\r\n        console.log('value:', event.value);\r\n\r\n        let myCountries = [];\r\n            if(event.value.length &gt; 0) {\r\n                for(let i = 0; i &lt; event.value.length; i++) {\r\n                    myCountries.push({\r\n                        id: event.value[i].id\r\n                    });\r\n                }\r\n            } \r\n\r\n         console.log(myCountries);\r\n\r\n    }\r\n\r\n}<\/pre>\n<p>Funkcija  <span class=\"lang:js decode:true  crayon-inline\">this.getCountries();<\/span>  dohva\u0107a popis svih dr\u017eava s API-ja. Unutar te funkcije vrtimo petlju kojom odabiremo koje parametre trebamo od API-ja jer ne trebaju nam svi parametri. Zna\u010di uzimao samo <span class=\"lang:js decode:true crayon-inline\">id<\/span>, <span class=\"lang:js decode:true crayon-inline\">population<\/span> i <span class=\"lang:js decode:true crayon-inline\">name<\/span>.<\/p>\n<pre class=\"lang:js decode:true   \" > if(this.countryOptions.length &gt; 0) {\r\n                for(let i = 0; i &lt; this.countryOptions.length; i++) {\r\n                    myCountries.push({\r\n                        id: this.countryOptions[i].alpha2Code,\r\n                        population: this.countryOptions[i].population,\r\n                        name: this.countryOptions[i].name\r\n                    });\r\n                }\r\n            } <\/pre>\n<p>Tako napunjen niz (<em>array<\/em>) proslijedimo ranije kreiranoj komponenti <span class=\"lang:js decode:true crayon-inline\">this.countries = this.passingFunction(myCountries);<\/span>.<\/p>\n<p>I na kraju kada odaberemo \u017eeljene vrijednosti opet vrtimo petlju izdvajaju\u0107i samo <span class=\"lang:js decode:true crayon-inline\">id<\/span>.<\/p>\n<pre class=\"lang:js decode:true     \" >let myCountries = [];\r\n            if(event.value.length &gt; 0) {\r\n                for(let i = 0; i &lt; event.value.length; i++) {\r\n                    myCountries.push({\r\n                        id: event.value[i].id\r\n                    });\r\n                }\r\n            } <\/pre>\n<p>Na kraju to izgleda ovako:<\/p>\n<p><a href=\"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete-api.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete-api.gif\" alt=\"Ionic 3 \u2013 select, search i autocomplete komponenta\" width=\"1055\" height=\"717\" class=\"aligncenter size-full wp-image-6059\" \/><\/a><\/p>\n<h2>Zaklju\u010dak<\/h2>\n<p>I to je sve. Ova se tema mo\u017ee obraditi na vi\u0161e na\u010dina, ali vjerujem da je i ovo dovoljno da dobijete uvid u jedan od na\u010dina kako rije\u0161iti pitanje <em>Ionic autocomplete<\/em> funkcionalnosti.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Iako sam ve\u0107 objavio blog post na temu Ionic 3 autocomplete funkcionalnosti mislim da \u0107e vam se primjer iz ovog blog posta jo\u0161 vi\u0161e svidjeti. Cijela se funkcionalnost temelji na pro\u0161irivanju mogu\u0107nosti ve\u0107 postoje\u0107e Ionic Select komponente. Postavljanje aplikacije Za po\u010detak je potrebno kreirati novi Ionic projekt $ ionic start Ionic3SelectSearchAutocomplete blank $ cd Ionic3SelectSearchAutocomplete &hellip; <a href=\"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/\" class=\"more-link\">Nastavi \u010ditati <span class=\"screen-reader-text\">Ionic 3 &#8211; select, search i autocomplete komponenta<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":6022,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[564,351],"tags":[420,400,463,462],"class_list":["post-6020","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mobile","category-razvoj","tag-autocomplete","tag-ionic-3","tag-komponenta","tag-search"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ionic 3 - select, search i autocomplete komponenta - Tomislav Stankovi\u0107<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/\" \/>\n<meta property=\"og:locale\" content=\"hr_HR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ionic 3 - select, search i autocomplete komponenta - Tomislav Stankovi\u0107\" \/>\n<meta property=\"og:description\" content=\"Iako sam ve\u0107 objavio blog post na temu Ionic 3 autocomplete funkcionalnosti mislim da \u0107e vam se primjer iz ovog blog posta jo\u0161 vi\u0161e svidjeti. Cijela se funkcionalnost temelji na pro\u0161irivanju mogu\u0107nosti ve\u0107 postoje\u0107e Ionic Select komponente. Postavljanje aplikacije Za po\u010detak je potrebno kreirati novi Ionic projekt $ ionic start Ionic3SelectSearchAutocomplete blank $ cd Ionic3SelectSearchAutocomplete &hellip; Nastavi \u010ditati Ionic 3 &#8211; select, search i autocomplete komponenta\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/\" \/>\n<meta property=\"og:site_name\" content=\"Tomislav Stankovi\u0107\" \/>\n<meta property=\"article:published_time\" content=\"2017-09-16T16:57:18+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-01-05T17:52:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"825\" \/>\n\t<meta property=\"og:image:height\" content=\"510\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tomislav Stankovi\u0107\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Napisao\/la\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tomislav Stankovi\u0107\" \/>\n\t<meta name=\"twitter:label2\" content=\"Procijenjeno vrijeme \u010ditanja\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minuta\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/\"},\"author\":{\"name\":\"Tomislav Stankovi\u0107\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/#\\\/schema\\\/person\\\/0329c549c57700034ea77f5d3d78396d\"},\"headline\":\"Ionic 3 &#8211; select, search i autocomplete komponenta\",\"datePublished\":\"2017-09-16T16:57:18+00:00\",\"dateModified\":\"2019-01-05T17:52:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/\"},\"wordCount\":441,\"commentCount\":9,\"publisher\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/#\\\/schema\\\/person\\\/0329c549c57700034ea77f5d3d78396d\"},\"image\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/ionic3-search-select-autocomplete.jpg\",\"keywords\":[\"Autocomplete\",\"Ionic 3\",\"komponenta\",\"search\"],\"articleSection\":[\"Mobile\",\"Razvoj\"],\"inLanguage\":\"hr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/\",\"url\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/\",\"name\":\"Ionic 3 - select, search i autocomplete komponenta - Tomislav Stankovi\u0107\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/ionic3-search-select-autocomplete.jpg\",\"datePublished\":\"2017-09-16T16:57:18+00:00\",\"dateModified\":\"2019-01-05T17:52:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#breadcrumb\"},\"inLanguage\":\"hr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"hr\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/ionic3-search-select-autocomplete.jpg\",\"contentUrl\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2017\\\/09\\\/ionic3-search-select-autocomplete.jpg\",\"width\":825,\"height\":510,\"caption\":\"Ionic 3: Select, search & autocomplete\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/ionic-3-autocomplete-select-search\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Po\u010detna stranica\",\"item\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ionic 3 &#8211; select, search i autocomplete komponenta\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/\",\"name\":\"Tomislav Stankovi\u0107\",\"description\":\"Sam svoj bloger\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/#\\\/schema\\\/person\\\/0329c549c57700034ea77f5d3d78396d\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"hr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/#\\\/schema\\\/person\\\/0329c549c57700034ea77f5d3d78396d\",\"name\":\"Tomislav Stankovi\u0107\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"hr\",\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/cropped-TomislavStankovic.jpg\",\"url\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/cropped-TomislavStankovic.jpg\",\"contentUrl\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/cropped-TomislavStankovic.jpg\",\"width\":248,\"height\":165,\"caption\":\"Tomislav Stankovi\u0107\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/cropped-TomislavStankovic.jpg\"},\"description\":\"Bloger \u0161irokog raspona interesa od kojih dio voli objaviti na ovom blogu. U neslobodno vrijeme Angular developer mobilnih i web aplikacija.\",\"sameAs\":[\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/tomislavstankovic\\\/\"],\"url\":\"https:\\\/\\\/www.tomislavstankovic.com\\\/blog\\\/author\\\/tomislavstankovic\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ionic 3 - select, search i autocomplete komponenta - Tomislav Stankovi\u0107","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/","og_locale":"hr_HR","og_type":"article","og_title":"Ionic 3 - select, search i autocomplete komponenta - Tomislav Stankovi\u0107","og_description":"Iako sam ve\u0107 objavio blog post na temu Ionic 3 autocomplete funkcionalnosti mislim da \u0107e vam se primjer iz ovog blog posta jo\u0161 vi\u0161e svidjeti. Cijela se funkcionalnost temelji na pro\u0161irivanju mogu\u0107nosti ve\u0107 postoje\u0107e Ionic Select komponente. Postavljanje aplikacije Za po\u010detak je potrebno kreirati novi Ionic projekt $ ionic start Ionic3SelectSearchAutocomplete blank $ cd Ionic3SelectSearchAutocomplete &hellip; Nastavi \u010ditati Ionic 3 &#8211; select, search i autocomplete komponenta","og_url":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/","og_site_name":"Tomislav Stankovi\u0107","article_published_time":"2017-09-16T16:57:18+00:00","article_modified_time":"2019-01-05T17:52:58+00:00","og_image":[{"width":825,"height":510,"url":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.jpg","type":"image\/jpeg"}],"author":"Tomislav Stankovi\u0107","twitter_card":"summary_large_image","twitter_misc":{"Napisao\/la":"Tomislav Stankovi\u0107","Procijenjeno vrijeme \u010ditanja":"14 minuta"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#article","isPartOf":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/"},"author":{"name":"Tomislav Stankovi\u0107","@id":"https:\/\/www.tomislavstankovic.com\/blog\/#\/schema\/person\/0329c549c57700034ea77f5d3d78396d"},"headline":"Ionic 3 &#8211; select, search i autocomplete komponenta","datePublished":"2017-09-16T16:57:18+00:00","dateModified":"2019-01-05T17:52:58+00:00","mainEntityOfPage":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/"},"wordCount":441,"commentCount":9,"publisher":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/#\/schema\/person\/0329c549c57700034ea77f5d3d78396d"},"image":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#primaryimage"},"thumbnailUrl":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.jpg","keywords":["Autocomplete","Ionic 3","komponenta","search"],"articleSection":["Mobile","Razvoj"],"inLanguage":"hr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/","url":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/","name":"Ionic 3 - select, search i autocomplete komponenta - Tomislav Stankovi\u0107","isPartOf":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#primaryimage"},"image":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#primaryimage"},"thumbnailUrl":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.jpg","datePublished":"2017-09-16T16:57:18+00:00","dateModified":"2019-01-05T17:52:58+00:00","breadcrumb":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#breadcrumb"},"inLanguage":"hr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/"]}]},{"@type":"ImageObject","inLanguage":"hr","@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#primaryimage","url":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.jpg","contentUrl":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2017\/09\/ionic3-search-select-autocomplete.jpg","width":825,"height":510,"caption":"Ionic 3: Select, search & autocomplete"},{"@type":"BreadcrumbList","@id":"https:\/\/www.tomislavstankovic.com\/blog\/ionic-3-autocomplete-select-search\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Po\u010detna stranica","item":"https:\/\/www.tomislavstankovic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Ionic 3 &#8211; select, search i autocomplete komponenta"}]},{"@type":"WebSite","@id":"https:\/\/www.tomislavstankovic.com\/blog\/#website","url":"https:\/\/www.tomislavstankovic.com\/blog\/","name":"Tomislav Stankovi\u0107","description":"Sam svoj bloger","publisher":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/#\/schema\/person\/0329c549c57700034ea77f5d3d78396d"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.tomislavstankovic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"hr"},{"@type":["Person","Organization"],"@id":"https:\/\/www.tomislavstankovic.com\/blog\/#\/schema\/person\/0329c549c57700034ea77f5d3d78396d","name":"Tomislav Stankovi\u0107","image":{"@type":"ImageObject","inLanguage":"hr","@id":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2019\/10\/cropped-TomislavStankovic.jpg","url":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2019\/10\/cropped-TomislavStankovic.jpg","contentUrl":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2019\/10\/cropped-TomislavStankovic.jpg","width":248,"height":165,"caption":"Tomislav Stankovi\u0107"},"logo":{"@id":"https:\/\/www.tomislavstankovic.com\/blog\/wp-content\/uploads\/2019\/10\/cropped-TomislavStankovic.jpg"},"description":"Bloger \u0161irokog raspona interesa od kojih dio voli objaviti na ovom blogu. U neslobodno vrijeme Angular developer mobilnih i web aplikacija.","sameAs":["https:\/\/www.tomislavstankovic.com\/blog\/","https:\/\/www.linkedin.com\/in\/tomislavstankovic\/"],"url":"https:\/\/www.tomislavstankovic.com\/blog\/author\/tomislavstankovic\/"}]}},"_links":{"self":[{"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/posts\/6020","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/comments?post=6020"}],"version-history":[{"count":36,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/posts\/6020\/revisions"}],"predecessor-version":[{"id":7549,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/posts\/6020\/revisions\/7549"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/media\/6022"}],"wp:attachment":[{"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/media?parent=6020"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/categories?post=6020"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tomislavstankovic.com\/blog\/wp-json\/wp\/v2\/tags?post=6020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}