Reputation: 23
I've created a searchable table, which works as expected on desktop. Testing on mobile however, the search function doesn't return the filtered drivers as expected.
I've tried remote debugging. Strangely if I input to my phone from my PC, the search works. As soon as I try to input from my phone directly, the search doesn't filter correctly.
In my template:
<input type="text" v-model="searchQuery" @input="filterStandings" placeholder="search driver">
<table class="standings">
<thead>
<th>Position</th>
<th>Driver Name</th>
<th>Nationality</th>
<th>Team</th>
<th>Wins</th>
<th>Points</th>
</thead>
<tbody>
<tr v-for="standing in filteredStandings" :key="standing.position" class="standing">
<td>{{standing.position }}</td>
<td>{{standing.Driver.driverId | last-name | to-title-case}}</td>
<td>{{standing.Driver.nationality | to-title-case}}</td>
<td>{{standing.Constructors[0].constructorId | to-title-case}}</td>
<td>{{standing.wins }}</td>
<td>{{standing.points}}</td>
</tr>
</tbody>
</table>
script:
<script>
import styles from "../styles/styles.scss";
import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
export default {
name: "CurrentStandings",
data() {
return {
searchQuery: ""
};
},
created() {
this.fetchStandings();
},
computed: {
...mapState(["standings", "search"]),
...mapGetters(["filteredStandings"])
},
methods: {
...mapActions(["fetchStandings"]),
...mapMutations(["set_search"]),
filterStandings() {
this.$store.commit("set_search", this.searchQuery);
}
}
};
</script>
Finally, my store:
import axios from 'axios';
const state = {
standings: [],
search: '',
};
const getters = {
filteredStandings: state => state.standings.filter(standing => standing.Driver.driverId.match(state.search)),
};
const mutations = {
set_standings: (state, standings) => (state.standings = standings),
set_search: (state, search) => (state.search = search),
};
const actions = {
async fetchStandings({ commit }) {
const response = await axios.get('https://ergast.com/api/f1/current/driverStandings.json');
commit('set_standings', response.data.MRData.StandingsTable.StandingsLists[0].DriverStandings); // response.data is passed to 'standings' in the mutation (2nd arg)
},
};
export default {
state,
getters,
actions,
mutations,
};
Here's the link to my app if you'd like to see for yourself. Thanks in advance!
Upvotes: 0
Views: 260
Reputation: 29102
You seem to have a case sensitivity issue.
When I try to type a value on Android Chrome it automatically sets the first character to uppercase. So if I try to type in ham
it'll be entered as Ham
. This doesn't match anything. Exactly the same thing happens if I type in Ham
on desktop Chrome.
The culprit appears to be this:
standing => standing.Driver.driverId.match(state.search)
The case sensitivity is just the first problem. match
expects a regular expression and passing it a string will be treated as equivalent to new RegExp(state.search)
. It's unlikely this is what you want, e.g. typing in [
will give an error.
Something like this might be closer:
standing => standing.Driver.driverId.toLowerCase().includes(state.search.toLowerCase())
I'm glossing over potential problems with different locales here but chances are this will give you what you want.
There are further issues with the code. The current search value is being held in multiple different places. You really should decide whether you want to hold it in the store or on the component and get rid of the other. Either way could be made to work. Trying to synchronise multiple sources of truth is likely to cause you problems further down the road. If you want to go all-in with the store then you may find https://vuex.vuejs.org/guide/forms.html helpful.
Upvotes: 1
Reputation: 8617
Try using
filterStandings({ type, target }) {
this.$store.commit("set_search", target.value);
}
The value in the store may be stale in some fashion, causing some sort of cyclical "blank" on slower devices? You could try using chrome CPU throttling to test this theory.
In this case you are taking the input directly from the event rather than relying on a possible stale value.
Should you be using v-model with vuex this way? See: https://vuex.vuejs.org/guide/forms.html
Upvotes: 0