How to use vue getters to find a value inside an object? - vue.js

I want to get a specific value of an object inside the state of vuex.
Let me show you what I mean:
import { createStore } from "vuex";
export default createStore({
state: {
cards: [{
title: "Blog 1",
htmlCode: "This is blog 1",
index: 1,
},
{
title: "Blog 2",
htmlCode: "This is blog 2",
index: 2,
},
{
title: "Blog 3",
htmlCode: "This is blog 3",
index: 3,
},
{
title: "Blog 4",
htmlCode: "This is blog 4",
index: 4,
},
{
title: "Blog 5",
htmlCode: "This is blog 5",
index: 5,
},
{
title: "Blog 6",
htmlCode: "This is blog 6",
index: 6,
},
{
title: "Blog 7",
htmlCode: "This is blog 7",
index: 7,
},
],
},
getters: {
getTodoById: (state) => (id) => {
return state.cards.find(todo => todo.index === id)
}
},
mutations: {},
actions: {},
modules: {},
});
Now if I insert this value in my code: <p>{{ this.$store.getters.getTodoById(2) }}</p>, I get this as result: { "title": "Blog 2", "htmlCode": "This is blog 2", "index": 2 }
What I want, is the value of for examplehtmlCode and that result would be This is blog 2.
Hopefully someone understands what I mean.
For clarity: I want this result in the browser: This is blog 2
It is very important for my website that it is done with vuex getters.

This is a posible solution
getTodoById: (state) => (id) => {
const todo = state.cards.find(todo => todo.index === id)
return todo.htmlCode
}
Other solution is create a todo data in the componente and in the created() add your getter and asign to this data.
data() {
return {
todo: null,
};
},
created() {
this.todo = this.$store.getters.getTodoById(id) // for example extracted by the route
},
<p>{{ todo.htmlCode }}</p>

This should work.
<p>{{ this.$store.getters.getTodoById(2).htmlCode}}</p>

Related

Mocking GraphQL API with MSW for Testing

I'm trying to mock graphql API for testing react app but facing a problem
the handler is:
import { graphql } from 'msw'
export const postsGql = [
{
userId: 1,
id: 1,
title: 'first post title',
body: 'first post body',
},
{
userId: 2,
id: 5,
title: 'second post title',
body: 'second post body',
}
]
Define handlers that catch the corresponding requests and returns the mock data.
export const graphqlHandlers = [
graphql.query('posts', async(req, res, ctx) => {
return res(
ctx.data(
postsGql,
),
)
}),
]
my test file:
it('Should return posts when clicking fetch with graphql button', async() => {
render(<ApolloProvider client={client}>
<App />
</ApolloProvider>)
expect(screen.getByRole('heading', { name: 'MSW Testing Library Example', level: 1 })).toBeDefined()
userEvent.click(screen.getByRole('button', { name: 'Fetch Posts GraphQL' }))
await waitForElementToBeRemoved(() => screen.queryByLabelText('loading'))
postsGql.forEach((posts) => {
expect(screen.getByRole('heading', { name: posts.title, level: 2 })).toBeDefined()
expect(screen.getByText(posts.body)).toBeDefined()
})
})
but faced this error:
Missing field 'posts' while writing result [
{
"userId": 1,
"id": 1,
"title": "first post title",
"body": "first post body"
},
{
"userId": 2,
"id": 5,
"title": "second post title",
"body": "second post body"
}
]
I will appreciate any kind of help
thanks

how to pass i18n data $t as prop to a component

in a normal way with out translation but i want to translate the two object array and bind into a component
<InfoNews
v-for="infonew in infonews"
:id="infonew.id"
:title="infonew.title"
:content="infonew.content"
/>
data() {
return {
infonews: [
{
id: "01",
title: "what we do",
content:"industke aecimen book. ",
},
{
id: "02",
title: "our mission",
content:"ggdddg",
},
],
};
Make infonews a computed property. The title and content of each should be the translation keys.
export default {
computed: {
infonews() {
return [
{
id: "01",
title: this.$t("what we do"),
content: this.$t("industke aecimen book"),
},
{
id: "02",
title: this.$t("our mission"),
content: this.$t("ggdddg"),
},
]
};
}
}

How to populate a v-select component with json data coming from axios.get

I am having a hard time trying to populate a v-select component with data from backend. The backend data is in json format.
The array 'items_category' is not storing the data. So I see "No data available" in my v-select. Can anyone help me. Thanks. This is my code:
<v-select v-model="category" :items="items_category" chips dense></v-select>
data () {
return {
category: '',
items_category: [],
categories: [],
i: 0
}
},
created () {
this.initialize()
},
methods: {
initialize () {
axios.get('http://localhost:4000/categories', {
})
.then(response => {
this.categories = response.data
for (this.i=0; this.i<this.categories.length; this.i++) {
this.items_category[this.i] = this.categories[this.i].category_name
}
})
.catch(function (error) {
console.log(error);
})
}
}
This is my json (http://localhost:4000/categories):
[
{
"id": 1,
"category_name": "Name 1",
"category_description": "Description 1"
},
{
"id": 2,
"category_name": "Premium",
"category_description": "Description 2"
},
{
"id": 3,
"category_name": "Free",
"category_description": "Description 3"
}
]
Ok I got it correct by using the push method
this.items_category.push(this.categories[this.i].category_name)

How to implement Groupping in Nativescript Vue RadDataForm?

Want to use Fields grouping Documention is not prvided event the topic of grouping nor the example. Most of the example are using typescript. Event the Google is not showing the result.
<RadDataForm
ref="dataform"
:source="customerForm"
:metadata="customerFormMetadata"
:groups="groups"
/>
customerFormMetadata: {
isReadOnly: false,
commitMode: "Immediate",
validationMode: "Immediate",
propertyAnnotations: [
{
name: "customer_name_1",
displayName: "Customer Name",
index: 0,
groupName: "Personal",
editor: "Text"
},
groups: [
Object.assign(new PropertyGroup(), {
name: "Personal",
collapsible: true,
collapsed: false
}),
Object.assign(new PropertyGroup(), {
name: "Address",
collapsible: true,
collapsed: true
})
],
Grouping doesn't require any addtional configuration while using with Vue, it's pretty straight forward as described in the core docs.
Example
<template>
<Page class="page">
<ActionBar title="Home" class="action-bar" />
<RadDataForm :source="person" :metadata="groupMetaData" />
</Page>
</template>
<script>
import Vue from "nativescript-vue";
import RadDataForm from "nativescript-ui-dataform/vue";
Vue.use(RadDataForm);
export default {
data() {
return {
person: {
name: "John",
age: 23,
email: "john#company.com",
city: "New York",
street: "5th Avenue",
streetNumber: 11
},
groupMetaData: {
propertyAnnotations: [{
name: "city",
index: 3,
groupName: "Address",
editor: "Picker",
valuesProvider: [
"New York",
"Washington",
"Los Angeles"
]
},
{
name: "street",
index: 4,
groupName: "Address"
},
{
name: "streetNumber",
index: 5,
editor: "Number",
groupName: "Address"
},
{
name: "age",
index: 1,
editor: "Number",
groupName: "Main Info"
},
{
name: "email",
index: 2,
editor: "Email",
groupName: "Main Info"
},
{
name: "name",
index: 0,
groupName: "Main Info"
}
]
}
};
}
};
</script>
Edit:
As discussed in the docs, to make the Group collapsible use the groupUpdate event.
onGroupUpdate: function(args) {
let nativeGroup = args.group;
if (args.ios) {
nativeGroup.collapsible = true;
} else {
nativeGroup.setExpandable(true);
}
}
Updated Playground

VueJS implement go to prev menu

I am writing an app where a fixed length list gets generated based on the nested JSONArray. Whenever any elements gets clicked from the list and if it has a "sub data" array,the list gets populated with this "sub data". Basically, you can think of it as menus which has submenus and those submenus has subsubmenus and so on.
I have implemented two methods for going to sublevels [next()] which works fine but I don't know how to implement prev() method to go one level up in the menu. Currently, I can make it go one level up but if user is inside more than two level then I don't know how to keep the track of all above levels.
Here is the codepen -
codepen
let JSONModel = (_id, _lvl, _title, _data) => {
return {
id: _id,
lvl: _lvl,
title: _title,
data: _data
};
};
let Menu = [
{
id: "01",
lvl: "01",
title: "menu 1",
data: []
},
{
id: "02",
lvl: "01",
title: "menu 2",
data: []
},
{
id: "03",
lvl: "01",
title: "menu 3",
data: []
},
{
id: "04",
lvl: "01",
title: "menu 4",
data: [
{
id: "01",
lvl: "02",
title: "submenu 1",
data: []
},
{
id: "02",
lvl: "02",
title: "submenu 2",
data: [
{
id: "01",
lvl: "03",
title: "sub submenu 1",
data: []
},
{
id: "02",
lvl: "03",
title: "sub submenu 2",
data: []
},
{
id: "03",
lvl: "03",
title: "sub submenu 3",
data: []
},
{
id: "04",
lvl: "03",
title: "sub submenu 4",
data: []
}
]
},
{
id: "03",
lvl: "02",
title: "submenu 3",
data: []
},
{
id: "04",
lvl: "02",
title: "submenu 4",
data: []
}
]
}
];
let demo = new Vue({
el: "#app",
data: {
input: Menu,
prevMenu:[]
},
computed: {},
created: function () {
},
methods: {
next: function(val1,val2) {
if (val1.length != 0) {
this.input = val1;
this.prevMenu = val2;
console.log(this.prevMenu);
}
},
prev: function() {
console.log(this.prevMenu);
this.input = this.prevMenu;
}
}
});
$("#prevmenu").on("click", function() {
demo.prev();
});
Using your code, you can simply do this:
https://codepen.io/webkit_il/pen/bjebZR?editors=0011
next: function(val1,val2) {
if (val1.length != 0) {
this.input = val1;
this.prevMenu.push(val2);
}
},
prev: function() {
let _menu = this.prevMenu.slice(); // this is just to clone the array
this.input = _menu[_menu.length - 1];
this.prevMenu.pop();
}
changed your prevMenu into an array, then everytime you
go back just use the last one, and remove it from the array...
good luck!