<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
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
};
},
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);
},
}),
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']
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...
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')
})
},
}