How to add real time search with VueJS? - javascript

I want to add realtime search to find another users that are registered on my twitter clone. So, users are on backend (Firebase)
Users on backend and example of search that i want.
Here is my attempt:
<script>
export default {
data() {
return {
search: "",
users: ['Dummy', 'Users', 'From', 'Backend'],
};
},
methods: {
findUser(){
const result = this.users.find(user => user.includes(this.search))
console.log(result)
},
},
};
</script>
What am I doing wrong?

I think a computed property is better here to have the "real-time" changes, and a .filter to get the filtered list matching search:
new Vue({
el:"#app",
data() {
return {
search: "",
users: ['Dummy', 'Users', 'From', 'Backend'],
};
},
computed: {
filteredUsers(){
return this.users.filter(user =>
user.toLowerCase().includes(this.search.toLowerCase())
);
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="search"/>{{filteredUsers}}
</div>

For real-time search using API, you can use WATCH
Can be applied sorted on FIREBASE
https://firebase.google.com/docs/database/web/lists-of-data
var myUserId = firebase.auth().currentUser.uid;
var topUserPostsRef = firebase.database().ref('user-posts/' + myUserId).orderByChild('starCount')
There may be inconsistencies in the code, but I wanted to convey the essence
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="search"/>{{filteredUsers}}
</div>
new Vue({
el:"#app",
data() {
return {
search: null,
users: []
};
},
computed: {
filteredUsers(){
return this.users.filter(user =>
user.toLowerCase().includes(this.search.toLowerCase())
);
},
},
watch: {
watchUser(search) {
if (search) {
this.searchPerson()
}
},
},
methods: {
searchPerson() {
this.loading = true;
this.fetchUsers()
.then(res => {
this.users = normalizeResponse(res)
this.loading = false
})
},
fetchUsers() {
return axios({
method: 'get',
url: '',
params: {
},
headers: {
'Content-type': 'application/json'
}
});
},
}
});

Related

apollo client offsetLimitPagination not working

I have a hook..
export function useLazyProposalList() {
const [getQueueData, { loading, data, error, fetchMore }] = useLazyQuery(PROPOSAL_LIST, {
fetchPolicy: 'no-cache',
});
const proposalList = React.useMemo(() => {
if (!data) {
return null;
}
return transformProposals(data);
}, [data]);
return {
getQueueData,
fetchMore,
loading,
data: proposalList,
error,
};
}
In the component
const {
getQueueData,
data: queueData,
fetchMore: fetchMoreProposals,
// loadMore: loadMore,
} = useLazyProposalList();
If user clicks on fetch more button, I call: fetchMoreProposals .
await fetchMoreProposals({
variables: {
offset: visibleProposalList.length,
},
});
but this doesn't update my data. I read that we should use offsetLimitPagination, but my data from query is not array itself. It's like this: queue { id: '1', items:[] } and because of this, offsetLimitPagination doesn't work. So I tried merge
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
queue: {
keyArgs: false,
merge(existing, incoming) {
console.log(existing, incoming);
if (!incoming) return existing;
if (!existing) return incoming;
},
},
},
},
}
but in the console, it just prints refs instead of real data.
What could be the issue ?

I cannot implement a filter to my array in vue.js

I've been looking for quite a while but being a novice I can't find an answer.
I would like to filter my array with the id of a property I think is the wrong syntax.
Thanks for your help
components
export default {
props: ["user", "recette"],
data() {
return { email: this.$route.params.email };
},
components: {},
methods: {},
computed: {
filteredItems: function () {
return this.recette.filter((recettes) => {
return recettes.cat_recetteId === 1;
});
},
},
};
VIEW
<template>
<div>
<myrecette :recette="recette"/>
<myfooter />
</div>
</template>
<script>
import myrecette from "../components/recette";
import myfooter from "../components/myfooter";
export default {
name: "",
data() {
return {
recette: "",
user: "",
};
},
components: {
myrecette,
myfooter,
},
created: function() {
this.axios.get("http://localhost:3000/recette/all_recette/").then((res) => {
(this.recette = res.data.recette),
this.axios
.get(
"http://localhost:3000/user/rec_user/" + this.$route.params.email
)
.then((res) => {
this.user = res.data.user;
});
});
},
};
</script>
<style scoped></style>
NODE
router.get("/all_recette", (req, res) => {
db.recette
.findAll({
include: { all: true },
})
.then((recette) => {
if (recette) {
res.status(200).json({
recette: recette,
});
} else {
res.json("il n'y a pas de recettes");
}
})
.catch(err => {
res.json(err);
});
});
Here is my complete code as well as my node route.
My error return is
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: this.recette.filter is not a function"
The filter works by keeping items which return true, so if you want all items having a cat_recetteId of 1, you would change it to:
computed: {
filteredItems: function() {
if (!this.recette) return [];
return this.recette.filter((recettes) => {
return recettes.cat_recetteId === 1;
});
},
},
It's also good practice to use an arrow function in most cases inside of a computed.
Your filter callback function should return true or false. You're 1) not returning anything and 2) assigning a value (=) instead of doing a comparison (==/===).
computed: {
filteredItems: function() {
return this.recette.filter(function(recettes) {
return recettes.cat_recetteId === 1;
});
},
},

How to initialize data correctly in vue js?

It takes the initTableData and initTableFiltered after onChangeDistrict which i hope to not take it now, instead to take only the initTableFiltered
data () {
return {
data: []
}
},
created () {
this.initTableData()
},
methods() {
initTableData () {
db.collection('example').orderBy('owner_name', 'asc').get().then(res => {
res.forEach((doc) => {
this.data.push({
id: doc.id,
})
})
})
},
initTableFiltered () {
db.collection('filter').orderBy('name', 'asc').get().then(res => {
res.forEach((doc) => {
this.data.push({
id: doc.id,
})
})
}
onChangeDistrict () {
this.initTablefiltered()
}
}
So how to initialize the initTablefiltered freshly on onChangeDistrict?
Did you create data variable? This isn't in the code?
Ex:
export default {
data() {
return {
data: []
}
},
...
Without instantiate your data, this is not reactive...

Filtering a table by using vue multiselect

I'm trying to filter the results of a table by using vue-multiselect. I can see the selected values in the VUE dev tools as a part of multiselect component. How do I use these values to be used in filter() function to get the filtered table results.
Below you can see my JS script implementation and Template multiselect implementation as well.
JS Script
export default {
data: () => ({
policies: [],
selectedValues: [],
options: [],
}),
methods: {
filterByStatus: function({ label, value }) {
return this.policies.filter(data => {
let status= data.status.toLowerCase().match(this.selectedValues.toLowerCase());
},
Template
<multiselect
v-model="selectedValues"
:options="options"
:multiple="true"
label="label"
track-by="label"
placeholder="Filter by status"
#select="filterByStatus"
></multiselect>
Your select component is using the prop :multiple="true", this means the bound value selectedValues, with v-model, will return an array of policy objects.
Instead of using a filterByStatus function in the methods component options, create two computed properties.
One that computes an array of the selected policies statuses and another one that computes the filtered array of policies you want to display.
Script:
computed: {
selectedStatuses() {
const statuses = []
for (const { status } of this.selectedValues) {
statuses.push(status.toLowerCase())
}
return statuses
},
filteredPolicies() {
if (this.selectedStatuses.length === 0) {
return this.policies
}
const policies = []
for (const policy of this.policies) {
if (this.selectedStatuses.includes(policy.status.toLowerCase())) {
policies.push(policy)
}
}
return policies
}
}
Template:
<multiselect
v-model="selectedValues"
:options="options"
:multiple="true"
label="label"
track-by="label"
placeholder="Filter by status"
></multiselect>
Example:
Vue.config.productionTip = Vue.config.devtools = false
new Vue({
name: 'App',
components: {
Multiselect: window.VueMultiselect.default
},
data() {
return {
policies: [{
label: 'Policy A',
status: 'enabled'
}, {
label: 'Policy B',
status: 'disabled'
}, {
label: 'Policy C',
status: 'Deprecated'
}],
selectedValues: [],
options: [{
label: 'Enabled',
status: 'enabled'
}, {
label: 'Disabled',
status: 'DISABLED'
}, {
label: 'Deprecated',
status: 'DePrEcAtEd'
}]
}
},
computed: {
selectedStatuses() {
const statuses = []
for (const {
status
} of this.selectedValues) {
statuses.push(status.toLowerCase())
}
return statuses
},
filteredPolicies() {
if (this.selectedStatuses.length === 0) {
return this.policies
}
const policies = []
for (const policy of this.policies) {
if (this.selectedStatuses.includes(policy.status.toLowerCase())) {
policies.push(policy)
}
}
return policies
}
},
}).$mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect#2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
<div id="app">
<multiselect v-model="selectedValues" :options="options" :multiple="true" label="label" track-by="label" placeholder="Filter by status"></multiselect>
<pre>Policies: {{ filteredPolicies}}</pre>
</div>
It is better to keep the filter function inside computed.
computed:{
filterByStatus: function ({label, value}) {
return this.policies.filter((data) => {
return data.status && data.status.toLowerCase().includes(this.selectedValues.toLowerCase())
});
}
}
Using the filterByStatus in the template section will render the result in real time.
<div>{{filterByStatus}}</div>
you can use watch on selectedValues when any change or selection :
watch:{
selectedValues: function(value){
this.policies.filter(data => {
let status= data.status.toLowerCase().match(this.selectedValues.toLowerCase());
}
}
This how I did in one of my vue3 projects, where I had multiple dropdowns with multi-items can be selected to filter and with a text input box:
const filterByInput = (item: string) =>
item.toLowerCase().includes(state.searchInput.toLowerCase());
const filteredItems = computed(() => {
let fItems = JSON.parse(JSON.stringify(props.items));
if (state.searchInput) {
fItems = fItems.filter((item) => filterByInput(item.title));
}
if (state.filterByState.length) {
fItems = fItems.filter((item) => state.filterByState.includes(item.state));
}
if (state.filterByType.length) {
fItems = fItems.filter((item) => state.filterByType.includes(item.typeId));
}
if (state.filterByPublishing !== null) {
fItems = fItems.filter((item) => item.published === state.filterByPublishing);
}
return fItems;
// NOTE: other options that you can try (should be placed above `return`)
// const filterMultiSelect = (fItems, selectedItems, key) => {
// // OPT-1: foreach
// const arr = [];
// fItems.forEach((item) => {
// if (selectedItems.includes(item[key])) {
// arr.push(item);
// }
// });
// return arr;
// // OPT-2: filter
// return fItems.filter((item) => selectedItems.includes(item[key]));
// };
// if (state.filterByState.length) {
// fItems = filterMultiSelect(fItems, state.filterByType, 'typeId');
// }
});
You can find full code in this gist

How to push new data input to top on the list

hello how to push new data to the top list using vue.js and laravel, I tried but still failed, I hope someone can help with the problem.
this is my Controller
public function addComment()
{
$this->validate(request(), [
'comment' => 'required',
]);
$comment = [
'comment' => request()->comment,
'article_id' => request()->article_id,
'user_cid' => Auth::user()->user_cid,
];
$comment = ArticleComment::create($comment);
return new ArticleCommentResource($comment);
}
and this is my Vue.js Method
data() {
return {
data: [],
comments:[],
form: new Form({
comment: '',
article_id: this.articleid,
})
}
},
methods: {
onSubmit() {
this.showLoader = true
this.form.post('add-comment')
.then(response => {
console.log(response.article_id);
this.form.article_id = response.article_id;
});
},
}
how to handle it, thank you
I hope someone can help
Assuming your list simply loops through your comments array, you need to push the response at the first position of the list:
onSubmit() {
this.showLoader = true
this.form.post('add-comment')
.then(response => {
this.comments.unshift(response);
});
},
This assumes that response is the actual comment (I can't see into your form class).
<script>
import Form from 'form-backend-validation';
export default {
data:() => ({
form: new Form({
article_id: null,
}),
}),
mounted() {
this.fetch();
},
methods: {
async fetch() {
const response = await this.form.post('add-comment');
this.form.article_id = response.comment.article_id;
}
}
}
</script>
Please try this one.

Categories

Resources