2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-22 10:30:34 +03:00

WIP: v3 – remove onSearch callback prop (#811)

* remove onSearch callback prop

* update ajax docs

* docs formatting

* remove onSearch callback prop
This commit is contained in:
Jeff Sagal
2019-04-08 11:58:04 -07:00
committed by GitHub
parent b5e239c49c
commit 01ecee93d5
5 changed files with 66 additions and 100 deletions
+31 -19
View File
@@ -1,22 +1,25 @@
# AJAX Remote Option Loading ## Loading Options with AJAX
<CodePen url="POMeOX" height="400"/> 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:
The `onSearch` prop allows you to load options via ajax in a parent component **Search Event Parameters**
when the search text is updated. It is invoked with two parameters, `search` & `loading`. - `search {String}` The current search string
- `loading {Function}` Accepts a boolean parameter to toggle the loading state
```html
<v-select @search="fetchOptions" />
```
```js ```js
/** /**
* Accepts a callback function that will be run * Triggered when the search text changes.
* 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
* @param {search} String Current search text */
* @param {loading} Function Toggle loading class fetchOptions (search, loading) {
*/ // ... do some asynchronous stuff!
onSearch: {
type: Function,
default: false
}, },
``` ```
@@ -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 `loading` property to `true` - toggling the loading spinner. After your
asynchronous operation completes, call `loading(false)` to toggle it off. 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 When loading server side options, it can be useful to disable the
client side filtering. Use the `filterable` prop to disable filtering. 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 ```html
<div class="spinner" v-show="spinner">Loading...</div> <div class="spinner" v-show="spinner">Loading...</div>
``` ```
#### 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, 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. 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.
<CodePen url="POMeOX" height="400"/>
+3 -4
View File
@@ -2,9 +2,8 @@
Install with yarn: Install with yarn:
```bash ```bash
yarn add vue-select yarn add vue-select
```
or, using NPM: # or, using NPM
```
npm install vue-select 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'; 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 ```scss
@import "vue-select/src/scss/vue-select.scss"; @import "vue-select/src/scss/vue-select.scss";
-2
View File
@@ -1,5 +1,3 @@
# Dropdown Options
## Options Prop ## Options Prop
`vue-select` accepts arrays of primitive values or objects to use as options through the `options` prop: `vue-select` accepts arrays of primitive values or objects to use as options through the `options` prop:
+18 -31
View File
@@ -7,51 +7,38 @@ export default {
*/ */
loading: { loading: {
type: Boolean, 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 { return {
mutableLoading: false mutableLoading: false,
}; };
}, },
watch: { watch: {
/** /**
* If a callback & search text has been provided, * Anytime the search string changes, emit the
* invoke the onSearch callback. * '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() { search () {
if (this.search.length > 0) { this.$emit('search', this.search, this.toggleLoading);
this.onSearch(this.search, this.toggleLoading);
this.$emit("search", this.search, this.toggleLoading);
}
}, },
/** /**
* Sync the loading prop with the internal * Sync the loading prop with the internal
* mutable loading value. * mutable loading value.
* @param val * @param val
*/ */
loading(val) { loading (val) {
this.mutableLoading = val; this.mutableLoading = val;
} },
}, },
methods: { methods: {
@@ -62,11 +49,11 @@ export default {
* @param toggle Boolean * @param toggle Boolean
* @returns {*} * @returns {*}
*/ */
toggleLoading(toggle = null) { toggleLoading (toggle = null) {
if (toggle == null) { if (toggle == null) {
return (this.mutableLoading = !this.mutableLoading); return (this.mutableLoading = !this.mutableLoading);
} }
return (this.mutableLoading = toggle); return (this.mutableLoading = toggle);
} },
} },
}; };
+14 -44
View File
@@ -1,4 +1,6 @@
import { selectWithProps } from "../helpers"; import { selectWithProps } from "../helpers";
import { shallowMount } from '@vue/test-utils';
import vSelect from '../../src/components/Select';
describe("Asynchronous Loading", () => { describe("Asynchronous Loading", () => {
it("can toggle the loading class", () => { it("can toggle the loading class", () => {
@@ -11,33 +13,6 @@ describe("Asynchronous Loading", () => {
expect(Select.vm.mutableLoading).toEqual(true); 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", () => { it("should trigger the search event when the search text changes", () => {
const Select = selectWithProps(); const Select = selectWithProps();
@@ -49,7 +24,7 @@ describe("Asynchronous Loading", () => {
expect(events.length).toEqual(1); 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(); const Select = selectWithProps();
Select.vm.search = "foo"; Select.vm.search = "foo";
@@ -57,30 +32,25 @@ describe("Asynchronous Loading", () => {
const events = Select.emitted("search"); const events = Select.emitted("search");
expect(events).toContainEqual(["foo", Select.vm.toggleLoading]); expect(events).toContainEqual(["", Select.vm.toggleLoading]);
expect(events.length).toEqual(1); expect(events.length).toEqual(2);
}); });
it("can set loading to false from the onSearch callback", () => { it("can set loading to false from the @search event callback", () => {
const Select = selectWithProps({ const Select = shallowMount(vSelect, {
onSearch: (search, loading) => loading(false) listeners: {
search: (search, loading) => {
loading(false)
},
},
}); });
Select.vm.search = "foo"; Select.vm.mutableLoading = true;
Select.vm.search = 'foo';
expect(Select.vm.mutableLoading).toEqual(false); 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", () => { it("will sync mutable loading with the loading prop", () => {
const Select = selectWithProps({ loading: false }); const Select = selectWithProps({ loading: false });
Select.setProps({ loading: true }); Select.setProps({ loading: true });