how can i make filter of tasks by name here? - vue.js

<template lang="pug">
.kanban
.statuses
.todo(#drop="onDrop($event,'todo')"
#dragenter.prevent
#dragover.prevent)
span To do
tasks-order-by-status(:tasks = 'taskTodo')
.inprogress(#drop="onDrop($event,'inprogress')"
#dragenter.prevent
#dragover.prevent)
span In Progress
tasks-order-by-status(:tasks = 'taskInprog')
.done(#drop="onDrop($event,'done')"
#dragenter.prevent
#dragover.prevent)
span Done
tasks-order-by-status(:tasks = 'taskDone')
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { TaskStatusEnum } from './../enums/TaskStatusEnum'
import TasksOrderByStatus from '#/components/TasksOrderByStatus.vue'
import { useStore } from 'vuex'
import { emitter } from '../main'
import { TaskInterface } from '#/types/task.interface'
export default defineComponent({
setup () {
const store = useStore()
const tasks = computed(() => store.state.tasks)
return {
tasks
}
},
components: {
TasksOrderByStatus
},
data () {
return {
TaskStatusEnum,
showDetailsModal: false,
task: '',
taskTodo: [] as TaskInterface[],
taskInprog: [] as TaskInterface[],
taskDone: [] as TaskInterface[]
}
},
methods: {
setArrayByStatuses () {
for (let i = 0; i < this.tasks.length; i++) {
if (this.tasks[i].status === TaskStatusEnum.INPROGRESS) {
const item = this.tasks[i]
this.taskInprog.push(item)
}
if (this.tasks[i].status === TaskStatusEnum.TODO) {
const item = this.tasks[i]
this.taskTodo.push(item)
}
if (this.tasks[i].status === TaskStatusEnum.DONE) {
const item = this.tasks[i]
this.taskDone.push(item)
}
}
}
},
mounted () {
this.setArrayByStatuses()
}
})
</script>
how can i make filter of tasks by name here?
I tried to do this
computed: {
filteredList () {
return this.tasks.filter(task => {
return task.name.toLowerCase().includes(this.search.toLowerCase())
})
}
},
but i have this error Property 'tasks' does not exist on type 'CreateComponentPublicInstance<{ [x: string & on${string}]: ((...args: any[]) => any) | undefined; } | { [x: string & on${string}]: undefined; }, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, ... 10 more ..., {}>'.
Property 'tasks' does not exist on type '{ $: ComponentInternalInstance; $data: {}; $props: { [x: string & on${string}]: ((...args: any[]) => any) | undefined; } | { [x: string & on${string}]: undefined; }; ... 10 more ...; $watch(source: string | Function, cb: Function, options?: WatchOptions<...> | undefined): WatchStopHandle; } & ... 4 more ... & Co...'.

The setup() method does not work like you expect, it will not initiate data attributes (https://v3.vuejs.org/guide/composition-api-setup.html#accessing-component-properties)
Use mounted() instead and assign
this.tasks = tasks
also add tasks to your data object.

Related

vuejs use data from parent, but parent data usually update

there are two .vue file and one is parent and another is child.
I am developing 'Sending file' function with Modal.
I will upload file data in parent.vue.
and when I click 'Send', child.vue will be popped up!
and I will choose, target who receive this file data.
and finally, I click 'Send' button, get connection to Backend server.
This is parent.vue
<<templete>>
<script>
export default {
name: 'BillingView',
components: {
EmailSender
},
data() {
return {
uploaded_file: '',
file_data: {},
is_uploaded: false,
popupVal: false
}
},
methods: {
sendEmail() {
if (this.is_uploaded == false) {
alert('Upload your file');
} else {
<< parsing file data>>
this.file_data = JSON.parse(JSON.stringify(this.parsed_uploaded_file));
this.popupVal = (this.popupVal) ? false : true
}
},
popupClose: function ( value ) {
this.popupVal = value
}
}
}
</script>
This is child.vue
<<templete>>
<script>
import axios from 'axios';
export default {
name: 'EmailSender',
props: {
popupVal: Boolean,
file_data: {
type: Object,
default: () => {
return {}
}
}
},
data: () => ({
}),
computed: {
popUp: {
get() {
return this.popupVal
},
}
},
created() {
},
methods: {
sendEmail() {
let req_data = {};
req_data ['file'] = file_data;
axios.post(process.env.VUE_APP_BASE_API + 'email/',
{
req_data ,
headers: {
'Content-Type': 'application/json;charset=UTF-8-sig'
}
}
).then(res => {
console.log('SEND EMAIL SUCCESS!!');
console.log('SEND EMAIL RESPONSE::', res, typeof (res));
})
.catch(function () {
console.log('SEND EMAIL FAILURE!!');
});
}
}
};
</script>
but here, "req_data ['file'] = file_data;" the file_data is empty, {}.
I expect when I update file_data in parent vue, child can know and use updated file data.
how can I do?
You have to make sure you send file_data as a prop to your component. e.g. Your component is 'myPopup' and you should use it as below to send file_data as a prop:
<myPopup :myData="file_data" >
In this case, you can get file_data as 'myData' in the child component as below
After changes, your props should be:
props: {
myData: {
type: Object,
default: () => {
return {}
}
}
},
Your function should be:
Also, don't forget to use 'this' keyword. this.myData instead of myData in function.
methods: {
sendEmail() {
let req_data = {};
req_data['file'] = this.myData;
// axios here
};
},

How do I pass a parameter to pinia getter in vue?

Here is my ThreadsStore
import { defineStore } from "pinia";
import sourceData from "#/data.json";
import { useUsersStore } from "../stores/UsersStore";
import { usePostsStore } from "../stores/PostsStore";
import { useForumsStore } from "../stores/ForumsStore";
import { findById, upsert } from "#/helpers";
export const useThreadsStore = defineStore("ThreadsStore", {
state: () => {
return {
threads: sourceData.threads,
};
},
getters: {
thread: (state) => {
return (id) => {
const thread = findById(state.threads, id);
return {
...thread,
get author() {
return findById(useUsersStore().users, thread.userId);
},
get repliesCount() {
return thread.posts.length - 1;
},
get contributorsCount() {
return thread.contributors.length;
},
};
};
},
},
actions: {
async createThread({ text, title, forumId }) {
const id = "ggqq" + Math.random();
const userId = useUsersStore().authId;
const publishedAt = Math.floor(Date.now() / 1000);
const thread = { forumId, title, publishedAt, userId, id };
this.threads.push(thread);
this.appendThreadToUser({ userId, threadId: id });
this.appendThreadToForum({ forumId, threadId: id });
usePostsStore().createPost({ text, threadId: id });
return findById(this.threads, id);
},
async updateThread({ title, text, id }) {
const thread = findById(this.threads, id);
const post = findById(usePostsStore().posts, thread.posts[0]);
const newThread = { ...thread, title };
const newPost = { ...post, text };
this.setThread({ thread: newThread });
this.setPost({ post: newPost });
return newThread;
},
appendThreadToForum({ forumId, threadId }) {
const forum = findById(useForumsStore().forums, forumId);
forum.threads = forum.threads || [];
forum.threads.push(threadId);
},
appendThreadToUser({ userId, threadId }) {
const user = findById(useUsersStore().users, userId);
user.threads = user.threads || [];
user.threads.push(threadId);
},
setPost({ post }) {
upsert(usePostsStore().posts, post);
},
setThread({ thread }) {
upsert(this.threads, thread);
},
},
});
Here is my page
<template>
<div class="col-large push-top">
<h1>
{{ thread.title }}
<router-link
:to="{ name: 'ThreadEdit', id: this.id }"
class="btn-green btn-small"
>
Edit Thread
</router-link>
</h1>
<p>
By <a href="#" class="link-unstyled">{{ thread.author.name }}</a
>, <AppDate :timestamp="thread.publishedAt" />.
<span
style="float: right; margin-top: 2px"
class="hide-mobile text-faded text-small"
>{{ thread.repliesCount }} replies by
{{ thread.contributorsCount }} contributors</span
>
</p>
<post-list :posts="threadPosts" />
<post-editor #save="addPost" />
</div>
</template>
<script>
import { mapState, mapActions } from "pinia";
import { useThreadsStore } from "../stores/ThreadsStore";
import { usePostsStore } from "../stores/PostsStore";
import PostList from "#/components/PostList";
import PostEditor from "#/components/PostEditor";
export default {
name: "ThreadShow",
components: {
PostList,
PostEditor,
},
props: {
id: {
required: true,
type: String,
},
},
computed: {
...mapState(useThreadsStore, ["threads", "thread"]),
...mapState(usePostsStore, ["posts"]),
threadPosts() {
return this.posts.filter((post) => post.threadId === this.id);
},
},
methods: {
...mapActions(usePostsStore, ["createPost"]),
addPost(eventData) {
const post = {
...eventData.post,
threadId: this.id,
};
this.createPost(post);
},
},
};
</script>
In my computed I would like to map thread from my store for use in the template. I have not been able to figure out how to pass the id parameter to pinia properly in order to get it to return the thread properly.
The tutorial I am following along with uses vuex but I wanted to figure out how to use pinia so the conversion has been somewhat confusing
For anyone who might have something similar in the future. You can pass in a value to a getter like so
...mapState(useThreadsStore, {
thread(store) {
return store.thread(this.id);
},
}),

vue-emoji-picker : import const from vuex module not yielding desired result

I am trying to add custom emoji set to vue-emoji-picker
based https://codepen.io/DCzajkowski/pen/gObWjEQ
I have implemented this with partial success. I get everything loaded, except "RECENT" not added to the emoji list. Any help is greatly appreciated.
//my store/index.js
import recentEmojis from "./modules/recentEmojis";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
recentEmojis,
},
// store/modules/recentEmojis/index.js
export const defaultEmojis = {
"Frequently used": {
thumbs_up: "+1",
red_hreat: "heart",
},
People: {
},
Nature: {
},
Objects: {
},
Places: {
},
Symbols: {
},};
const getName = (emoji) => {
console.log("getName");
const emojiMap = Object.values(defaultEmojis).reduce(
(a, b) => ({ ...a, ...b }),
{});
const object = Object.entries(emojiMap).find(
// eslint-disable-next-line no-unused-vars
([_name, value]) => value === emoji
);
return object ? object[0] : null;
};
export default {
namespaced: true,
defaultEmojis,
state: {
recentlyUsedEmojis: [],
},
mutations: {
recentlyUsedEmojis: (state, recentlyUsedEmojis) =>
(state.recentlyUsedEmojis = recentlyUsedEmojis),
},
actions: {
addEmojiToRecent: ({ state, commit }, emoji) => {
const name = getName(emoji);
const rest = state.recentlyUsedEmojis
.map(
// eslint-disable-next-line no-unused-vars
([_name, value]) => value
)
.includes(emoji)
? state.recentlyUsedEmojis.filter(
// eslint-disable-next-line no-unused-vars
([_name, value]) => value !== emoji
)
: state.recentlyUsedEmojis.length > 5
? state.recentlyUsedEmojis.slice(0, -1)
: state.recentlyUsedEmojis;
commit("recentlyUsedEmojis", [[name, emoji], ...rest])},},
getters: {
recentlyUsedEmojis: (state) =>
state.recentlyUsedEmojis.length
? { Recent: Object.fromEntries(state.recentlyUsedEmojis) }
: {},
},
}
//in my vue instance # src/pages/edtor.default.vue
...
<emoji-picker :emoji-table="emojis" #emoji="append" :search="search">
....
<script> import axios from "axios";
import EmojiPicker from "vue-emoji-picker"
import { defaultEmojis } from "../../store/modules/recentEmojis/index.js" // <<<<
export default { name: "ABCD", components: { EmojiPicker, },
...
computed: { emojis()
{ return { ...this.$store.getters.recentlyUsedEmojis, ...defaultEmojis } }, },
......
methods: {
append(emoji)
{ this.input += emoji this.$store.dispatch("recentEmojis/addEmojiToRecent", emoji) },
}
replaced
...this.$store.getters.recentlyUsedEmojis,
with
...this.$store.getters['recentEmojis/recentlyUsedEmojis']

API Call is not updating refs in vue composables

I am trying to make an api call with a vue composable.
This is the composable
import { isRef, ref, unref, watchEffect } from "vue";
import axios from "axios";
export function getData(url){
const data = ref(null)
const error = ref(null)
function doAxios(){
data.value = null
error.value = null
axios.get(unref(url))
.then(res => {
data.value = res.data
})
.catch(err => {
error.value = err
})
}
if(isRef(url)){
watchEffect(doAxios)
}else{
doAxios()
}
return { data, error }
}
However, when I import and try to use this composable in a component, the ref does not get updated even after the api call is successful
<script>
import { ref } from '#vue/reactivity'
import { computed, onMounted } from '#vue/runtime-core';
import { useStore } from 'vuex';
import { getData } from '#/composables/getData';
export default {
setup(props, context){
const store = useStore()
let pageConfig = ref({ title: 'Dashboard' })
let cards_data = ref([
{ name: 'Open orders', value: 16 },
{ name: 'Closed orders', value: 21 },
{ name: 'Businesses', value: 10 },
{ name: 'Funds', value: 2002 },
]);
const { data: config, error } = getData('config')
console.log(config.value)
onMounted(() => {
context.emit('pageConfig', pageConfig)
})
return{ cards_data, config, error }
}
}
</script>
The config still remains null even after...

How to add the total + 1 in the text span each time a notification using vue.js 2?

My vue component is like this :
<template>
...
<span v-if="total > 0" class="badge" id="total">{{ total }}</span>
...
</template>
<script>
import { mapGetters } from 'vuex'
export default {
mounted() {
this.initialMount()
},
computed: {
...mapGetters(['total'])
},
methods: {
initialMount() {
Echo.private('App.User.' + window.Laravel.authUser.id).notification((notification) => {
const a = $('#total').text()
const b= parseInt(a) + 1
$('#total').text(b)
})
},
}
}
</script>
My modules is like this :
import { set } from 'vue'
import notification from '../../api/notification'
import * as types from '../mutation-types'
const state = {
total: 0,
}
const getters = {
total: state => state.total
}
const actions = {
getNotificationList ({ commit,state })
{
notification.getList(
data => {
const notifications = data
commit(types.GET_NOTIFICATION,{ notifications });
},
errors => {
console.log(errors)
}
)
}
}
const mutations = {
[types.GET_NOTIFICATION] (state, { notifications }) {
state.total = notifications.length
}
}
export default {
state,
getters,
actions,
mutations
}
===================================================================
I want every notification, the notification number incremented by 1
My above code works, but it still using jquery
I want change it using vue.js
How can I do it?
You have to commit action into the sucess callback of Echo, but first you have to define mutation:
const mutations = {
[types.GET_NOTIFICATION] (state, { notifications }) {
state.total = notifications.length
},
inc (state) {
state.total++
}
}
And then, you can commit action
methods: {
initialMount() {
Echo.private('App.User.' + window.Laravel.authUser.id).notification((notification) => {
// Make sure you have imported store
store.commit('inc')
})
},
}