diff --git a/docs/guide/ajax.md b/docs/guide/ajax.md index c03ee4c..0837f18 100644 --- a/docs/guide/ajax.md +++ b/docs/guide/ajax.md @@ -1,22 +1,25 @@ -# AJAX Remote Option Loading +## Loading Options with AJAX - +The `search` event provides a hook to load options from a parent component +when the search text is updated. It is emitted with two parameters: + +**Search Event Parameters** +- `search {String}` The current search string +- `loading {Function}` Accepts a boolean parameter to toggle the loading state -The `onSearch` prop allows you to load options via ajax in a parent component -when the search text is updated. It is invoked with two parameters, `search` & `loading`. +```html + +``` ```js /** -* Accepts a callback function that will be run -* when the search text changes. The callback -* will be invoked with these parameters: -* -* @param {search} String Current search text -* @param {loading} Function Toggle loading class -*/ -onSearch: { - type: Function, - default: false + * Triggered when the search text changes. + * + * @param search {String} Current search text + * @param loading {Function} Toggle loading class + */ +fetchOptions (search, loading) { + // ... do some asynchronous stuff! }, ``` @@ -25,7 +28,7 @@ to the vue-select internal `loading` property. Call `loading(true)` to set the `loading` property to `true` - toggling the loading spinner. After your asynchronous operation completes, call `loading(false)` to toggle it off. -#### Disabling Filtering +## Disabling Filtering When loading server side options, it can be useful to disable the client side filtering. Use the `filterable` prop to disable filtering. @@ -44,17 +47,26 @@ filterable: { }, ``` -#### Loading Spinner +## Loading Spinner -Vue Select includes a default loading spinner that appears when the loading class is present. The `spinner` slot allows you to implement your own spinner. +Vue Select includes a default loading spinner that appears when the loading class is present. The +`spinner` slot allows you to implement your own spinner. ```html
Loading...
``` -#### Library Agnostic +## Library Agnostic -Since Vue.js does not ship with ajax functionality as part of the core library, it's up to you to process the ajax requests in your parent component. +Since Vue.js does not ship with ajax functionality as part of the core library, it's up to you to +process the ajax requests in your parent component. I recommend using [axios](https://github.com/axios/axios) for creating your applications HTTP layer, or [`fetch()`](https://github.com/github/fetch) for simple requests. + +## Example + +The [codepen example](https://codepen.io/sagalbot/pen/POMeOX) wraps up all the above concepts and +searches GitHub repositories. It also uses scoped slots to add some custom templating. + + diff --git a/docs/guide/install.md b/docs/guide/install.md index c4b7143..a50090f 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -2,9 +2,8 @@ Install with yarn: ```bash yarn add vue-select -``` -or, using NPM: -``` + +# or, using NPM npm install vue-select ``` @@ -23,7 +22,7 @@ The component itself does not include any CSS. You'll need to include it separat import 'vue-select/dist/vue-select.css'; ``` -You can also import the scss yourself for complete control of the component styles: +Alternatively, you can import the scss for complete control of the component styles: ```scss @import "vue-select/src/scss/vue-select.scss"; diff --git a/docs/guide/options.md b/docs/guide/options.md index 68992fb..4cab97c 100644 --- a/docs/guide/options.md +++ b/docs/guide/options.md @@ -1,5 +1,3 @@ -# Dropdown Options - ## Options Prop `vue-select` accepts arrays of primitive values or objects to use as options through the `options` prop: diff --git a/src/mixins/ajax.js b/src/mixins/ajax.js index 0040ce1..80d1950 100644 --- a/src/mixins/ajax.js +++ b/src/mixins/ajax.js @@ -7,51 +7,38 @@ export default { */ loading: { type: Boolean, - default: false + default: false, }, - - /** - * Accept a callback function that will be - * run when the search text changes. - * - * loading() accepts a boolean value, and can - * be used to toggle a loading class from - * the onSearch callback. - * - * @param {search} String Current search text - * @param {loading} Function(bool) Toggle loading class - */ - onSearch: { - type: Function, - default: function(search, loading) {} // eslint-disable-line no-unused-vars - } }, - data() { + data () { return { - mutableLoading: false + mutableLoading: false, }; }, watch: { /** - * If a callback & search text has been provided, - * invoke the onSearch callback. + * Anytime the search string changes, emit the + * 'search' event. The event is passed with two + * parameters: the search string, and a function + * that accepts a boolean parameter to toggle the + * loading state. + * + * @emits search */ - search() { - if (this.search.length > 0) { - this.onSearch(this.search, this.toggleLoading); - this.$emit("search", this.search, this.toggleLoading); - } + search () { + this.$emit('search', this.search, this.toggleLoading); }, + /** * Sync the loading prop with the internal * mutable loading value. * @param val */ - loading(val) { + loading (val) { this.mutableLoading = val; - } + }, }, methods: { @@ -62,11 +49,11 @@ export default { * @param toggle Boolean * @returns {*} */ - toggleLoading(toggle = null) { + toggleLoading (toggle = null) { if (toggle == null) { return (this.mutableLoading = !this.mutableLoading); } return (this.mutableLoading = toggle); - } - } + }, + }, }; diff --git a/tests/unit/Ajax.spec.js b/tests/unit/Ajax.spec.js index e9a7914..1a465fa 100755 --- a/tests/unit/Ajax.spec.js +++ b/tests/unit/Ajax.spec.js @@ -1,4 +1,6 @@ import { selectWithProps } from "../helpers"; +import { shallowMount } from '@vue/test-utils'; +import vSelect from '../../src/components/Select'; describe("Asynchronous Loading", () => { it("can toggle the loading class", () => { @@ -11,33 +13,6 @@ describe("Asynchronous Loading", () => { expect(Select.vm.mutableLoading).toEqual(true); }); - it("should trigger the onSearch callback when the search text changes", () => { - const propsData = { onSearch: () => {} }; - const spy = jest.spyOn(propsData, "onSearch"); - const Select = selectWithProps(propsData); - - Select.vm.search = "foo"; - - expect(spy).toHaveBeenCalled(); - }); - - it("should not trigger the onSearch callback if the search text is empty", () => { - let calledWith = []; - const propsData = { - onSearch: search => { - calledWith.push(search); - } - }; - const spy = jest.spyOn(propsData, "onSearch"); - const Select = selectWithProps(propsData); - - Select.vm.search = "foo"; - Select.vm.search = ""; - - expect(spy).toHaveBeenCalledTimes(1); - expect(calledWith).toEqual(["foo"]); - }); - it("should trigger the search event when the search text changes", () => { const Select = selectWithProps(); @@ -49,7 +24,7 @@ describe("Asynchronous Loading", () => { expect(events.length).toEqual(1); }); - it("should not trigger the search event if the search text is empty", () => { + it("should trigger the search event if the search text is empty", () => { const Select = selectWithProps(); Select.vm.search = "foo"; @@ -57,30 +32,25 @@ describe("Asynchronous Loading", () => { const events = Select.emitted("search"); - expect(events).toContainEqual(["foo", Select.vm.toggleLoading]); - expect(events.length).toEqual(1); + expect(events).toContainEqual(["", Select.vm.toggleLoading]); + expect(events.length).toEqual(2); }); - it("can set loading to false from the onSearch callback", () => { - const Select = selectWithProps({ - onSearch: (search, loading) => loading(false) + it("can set loading to false from the @search event callback", () => { + const Select = shallowMount(vSelect, { + listeners: { + search: (search, loading) => { + loading(false) + }, + }, }); - Select.vm.search = "foo"; + Select.vm.mutableLoading = true; + Select.vm.search = 'foo'; expect(Select.vm.mutableLoading).toEqual(false); }); - it("can set loading to true from the onSearch callback", () => { - const Select = selectWithProps({ - onSearch: (search, loading) => loading(true) - }); - - Select.vm.search = "foo"; - - expect(Select.vm.mutableLoading).toEqual(true); - }); - it("will sync mutable loading with the loading prop", () => { const Select = selectWithProps({ loading: false }); Select.setProps({ loading: true });