Allow preservation of user specified high/low range value when out of bounds
See original GitHub issueAllow Range Input to accept and maintain state of a minimum below the lowest in range, and/or a maximum higher than highest in product range.
What is your use case for such a feature
We use the Range Input for a price range selector. Unfortunately, it puts the burden of understanding the the high and low price boundaries on the customer. We also combine the information in the “selected filter” so that it reads more naturally (no mathematical syntax). In other words, we show the Selected Filter as a single $50 to $150
instead of the >= $50
and <= $150
pair.
Example:
Given:
- Product set has a lowest priced item of $100
- Product set has a highest priced item of $200
When:
- Customer enters a range of $50 to $150
Then:
- Currently
- The $50 low price is dropped from the input box
- Single selected filter appears as
<= $150
- Desired state
- The $50 low price remains in input box so user can confirm they provided a low range
- Selected filters includes
>=$25
(we would then combine these into a single UI element:$25 to $150
- but that’s beyond the scope of this feature request)
The fact that the >=$25
does nothing to reduce the product set is logically sensible from a programmer’s standpoint. Why apply it if it does nothing? However, the disappearance of the low range and absence of confirmation via the selected filters can be disorienting to a customer who “thought” they were trying to restrict within a range. They may try again. Even when they see the number disappear (which they may not have explicitly noticed at first), they may not understand why and feel like they’re doing something wrong, or get frustrated with the system not accepting their input.
What is your proposal
Include an unbounded
widget parameter to the RangeInput.vue
component that would allow the developer to override the default behavior and specify that the bounds need NOT be enforced (they would be by default to preserve present behavior & backwards compatibility):
// vue-instantsearch/src/components/RangeInput.vue
// Some care would need to be taken to allow the input fields to accept unbounded values
<template>
...
<input
type="number"
:class="[suit('input'), suit('input', 'min')]"
:step="step"
:min="unbounded ? false : state.range.min" // <== Turn off min/max for unbounded
:max="unbounded ? false : state.range.max" // <== Turn off min/max for unbounded
:placeholder="state.range.min" // <== might want to do something here too...
:value="values.min"
@change="minInput = $event.currentTarget.value"
/>
// And the logic would need to recognize the unbounded prop
export default {
name: 'RangeInput',
...
props: {
...
unbounded: { // <== Define new prop with backwards compatible default value
type: Boolean,
required: false,
default: false,
},
},
...
computed: {
widgetParams: {
return {
attribute: this.attribute,
min: this.min,
max: this.max,
precision: this.precision,
unbounded: this.unbounded, // <== Add to widgetParams that the connector will use
};
},
....
},
Then the connector would need to be updated to reflect this, which I think is pretty simple:
// instantsearch.js/es/connectors/range/connectRange.js
...
export default function connectRange(renderFn) {
var unmountFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
checkRendering(renderFn, withUsage());
return function () {
var widgetParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var attribute = widgetParams.attribute,
minBound = widgetParams.min,
maxBound = widgetParams.max,
unbounded = widgetParams.unbounded, // <== capture the unbounded state
...
var isGreaterThanCurrentRange = isValidMinCurrentRange && currentRangeMin <= newNextMin;
var isMinValid = isResetNewNextMin
|| isValidNewNextMin
&& (
unbounded ||!isValidMinCurrentRange || isGreaterThanCurrentRange // <== Allow too low when unbounded
);
...
var isMaxValid = isResetNewNextMax
|| isValidNewNextMax
&& (
unbounded || !isValidMaxCurrentRange || isLowerThanRange // <== Allow too high when unbounded
);
...
At this point, enabling the unbounded version of the Range Input would be as easy for the developer as adding the unbounded
attribute to the component:
<AisRangeInput :attribute="price.or.whatever.field" unbounded />
What is the version you are using?
- vue-instantsearch: 3.3.0
- instantsearch.js: 4.8.3
Other notes
I tried going down the route of making a custom widget and custom connector, but the documentation discourages this and prefers a feature request. 😄 Thus, this feature request. If there is anything in the way of a good example of creating a custom widget/connector for Vue, I’d love to see it.
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
Before jumping to making a PR, we’ll discuss this with the team so we can find possibly a different solution. I’ll get back to you once we’ve discussed it, but otherwise it’s just making two separate PRs, yes.
yes, that was meant to be https://github.com/algolia/vue-instantsearch/blob/master/src/components/StateResults.vue @frostydustpile.