lodash groupBy condition on params - lodash

I'm trying to convert this with lodash..... or maybe ES7
[
{
"name":"Rue Pierre",
"details":{
"name":"Rue Pierre"
}
},
{
"name":"Rue de Wavrin",
"details":{
"ref":"D 241",
"name":"Rue de Wavrin"
}
},
{
"name":"Rue de paris",
"details":{
"ref":"D 241",
"name":"Rue de paris"
}
}
]
in
{
"Rue Pierre": [
{ "name": "Rue Pierre", "details": { "name": "Rue Pierre Gilles de Gennes" }}
],
"D 241': [
{"name": "Rue de paris", "details": {"ref": "D 241", "name": "Rue de paris"}},
{"name": "Rue de Wavrin", "details": { "ref": "D 241", "name": "Rue de Wavrin" }}
]
}
If the property 'ref" exist i groupBy "ref" else groupBy "name".
It's possible in one step?
Thx

_.groupBy() accepts a predicate. In the predicate you can use _.get() to get the value of a path ('details.ref') from the object, and if the value is undefined use a default value (o.name) instead.
const data = [{"name":"Rue Pierre","details":{"name":"Rue Pierre"}},{"name":"Rue de Wavrin","details":{"ref":"D 241","name":"Rue de Wavrin"}},{"name":"Rue de paris","details":{"ref":"D 241","name":"Rue de paris"}}];
const result = _.groupBy(data, (o) => _.get(o, 'details.ref', o.name));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

Related

Data not updating properly on i18n lang switch

On my index page, loading it for the first time returns the correct data I need:
index.js
<script>
export default {
async asyncData({ store, i18n }) {
let lang
if (i18n.locale == "en") lang = 'en'
if (i18n.locale == "pt") lang = 'pt-PT'
if (i18n.locale == "fr") lang = 'fr'
try {
const services = await (await fetch(`${store.state.apiUrl}/project-categories?populate=*&locale=` + lang)).json()
const projects = await (await fetch(`${store.state.apiUrl}/projects?populate=*&locale=` + lang)).json()
const articles = await (await fetch(`${store.state.apiUrl}/articles?populate=*&locale=` + lang)).json()
console.log(projects.data)
return {
projects: projects.data,
articles: articles.data,
services: services.data
}
} catch (error) {
console.log(error)
}
}
}
</script>
Returned data in default english looks like this:
[
{
id: 1,
attributes: {
title: 'Space RTS Game',
slug: 'space-rts-game',
intro: 'A Space Real-Time-Strategy MMO Game Project ...',
body: '',
subtitle: 'Game Development',
createdAt: '2022-06-13T15:09:23.144Z',
updatedAt: '2022-06-16T11:42:58.215Z',
publishedAt: '2022-06-16T11:42:58.209Z',
locale: 'en',
cover: [Object],
images: [Object],
localizations: [Object]
}
},
(...)
]
But once I switch the lang to fr, the data is returned as observers:
Here is the used html for switching lang:
<template>
<nav>
<ul class="nav justify-content-end">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="javascript:void(0)" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ $root.$i18n.locale }}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<nuxt-link
v-for="locale in availableLocales"
:key="locale.code"
:to="switchLocalePath(locale.code)"
class="dropdown-item">{{ locale.name }}
</nuxt-link>
</div>
</li>
</ul>
</nav>
</template>
(...)
<script>
export default {
computed: {
availableLocales () {
return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale)
}
}
}
</script>
If I try to copy this (observers) object from my browser console into a text editor, I've got these results which is much more complex (but shows the translated data in french inside):
[
{
"id": 4,
"attributes": {
"title": "Jeu Spatial RTS",
"slug": "jeu-spatial-rts",
"intro": "Un projet de jeu MMO de stratégie en temps réel spatial utilisant des ressources basées sur NFT Casper - La plupart des éléments de conception du jeu sont déjà terminés. Le développement commence bientôt...",
"body": null,
"subtitle": "Dev. de Jeu",
"createdAt": "2022-06-16T08:33:39.761Z",
"updatedAt": "2022-06-16T18:09:49.524Z",
"publishedAt": "2022-06-16T11:44:12.561Z",
"locale": "fr",
"cover": {
"data": {
"id": 2,
"attributes": {
"name": "cover-surface-lg.jpg",
"alternativeText": "cover-surface-lg.jpg",
"caption": "cover-surface-lg.jpg",
"width": 370,
"height": 240,
"formats": {
"thumbnail": {
"name": "thumbnail_cover-surface-lg.jpg",
"hash": "thumbnail_cover_surface_lg_6b09d070dd",
"ext": ".jpg",
"mime": "image/jpeg",
"path": null,
"width": 240,
"height": 156,
"size": 10.98,
"url": "/uploads/thumbnail_cover_surface_lg_6b09d070dd.jpg"
}
},
"hash": "cover_surface_lg_6b09d070dd",
"ext": ".jpg",
"mime": "image/jpeg",
"size": 21.62,
"url": "/uploads/cover_surface_lg_6b09d070dd.jpg",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"createdAt": "2022-06-13T15:19:23.234Z",
"updatedAt": "2022-06-13T15:19:23.234Z"
}
}
},
"images": {
"data": null
},
"localizations": {
"data": [
{
"id": 1,
"attributes": {
"title": "Space RTS Game",
"slug": "space-rts-game",
"intro": "A Space Real-Time-Strategy MMO Game Project using NFTs Casper based assets - Most of the game design parts are already done. Development starting soon...",
"body": "",
"subtitle": "Game Development",
"createdAt": "2022-06-13T15:09:23.144Z",
"updatedAt": "2022-06-16T11:42:58.215Z",
"publishedAt": "2022-06-16T11:42:58.209Z",
"locale": "en"
}
},
{
"id": 5,
"attributes": {
"title": "Jogo RTS Espacial",
"slug": "jogo",
"intro": "Um projeto de jogo MMO de estratégia em tempo real espacial usando recursos baseados em NFTs Casper - A maioria das partes de design de jogos já está pronta. Desenvolvimento começando em breve...",
"body": null,
"subtitle": "Jogo Dev.",
"createdAt": "2022-06-16T08:34:11.701Z",
"updatedAt": "2022-06-16T18:10:08.725Z",
"publishedAt": "2022-06-16T11:44:18.058Z",
"locale": "pt-PT"
}
}
]
}
}
},
(...)
As you can notice, it starts now at id: 4 and page text in my page just disappeared once I switched the lang. I'm a beginner with Nuxt / Vue.Js and would be curious why this is happening and find clues on how to resolve that problem.
Thanks in advance!

vuex. Can't get access to object variable

look at my vuex code:
export default new Vuex.Store({
state: {
article: {},
slug: '',
},
actions: {
getArticleData(context, payload) {
axios.get('/api/article-json', { params: {slug:payload } }).then((response) =>{
context.commit('setArticleData', response.data.data);
});
}
},
getters: {
articleLikes(state) {
return state.article.statistic.likes;
},
articleViews(state) {
return state.article.statistic.views;
}
},
mutations: {
setArticleData(state, payload) {
state.article = payload;
},
setCurrentSlug(state, payload) {
state.slug = payload;
},
setCurrentStatistic(state, payload) {
state.statistic = payload;
}
}
})
the code works like this - getArticleData action set Data in article object.
In create() hook set article opbject:
{
"id": 14,
"title": "Deserunt ea natus pariatur sunt eum voluptatem.",
"img": "https://via.placeholder.com/600/5F113B/FFFFFF/?text=LARAVEL:8.*",
"body": " fugiat.",
"created_at": "1 месяц назад",
"comments": [
{
"id": 40,
"subject": "Impedit inventore quis.",
"body": "Qui rem ut beatae expedita nemo.",
"created_at": "2 дня назад"
},
{
"id": 41,
"subject": "Nam et sit.",
"body": "Dolor voluptas error eos quod.",
"created_at": "2 дня назад"
},
],
"tags": [
{
"id": 1,
"label": "Ut"
},
{
"id": 3,
"label": "Fugiat"
},
],
"statistic":
{
"likes": 7,
"views": 153
}
}
This object formed by Laravel resource
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'img' => $this->img,
'body' => $this->body,
'created_at' => $this->createdAtForHumans(),
'comments' => CommentResource::collection($this->whenLoaded('comments')),
'tags' => TagResource::collection($this->whenLoaded('tags')),
'statistic' => new StateResource($this->whenLoaded('state')),
];
}
I can't get access to article.statistic.views and article.statistic.likes from getters.
In views component i have code
computed: {
viewsNumber() {
return this.$store.getters.articleViews;
},
}
and template
<template>
<span class="badge bg-danger">{{viewsNumber}} <i class="far fa-eye"></i></span>
</template>
this is my console errors
app.js?id=80d6f0783c93a26b57e1:20787 [Vue warn]: Error in render: "TypeError: Cannot read property 'views' of undefined"
found in
---> <ViewsComponent> at resources/js/components/ViewsComponent.vue
<ArticleComponent> at resources/js/components/ArticleComponent.vue
<Root>
app.js?id=80d6f0783c93a26b57e1:22054 TypeError: Cannot read property 'views' of undefined
for comments and tags no problems. In comments component i have access to comments^
computed: {
article() {
return this.$store.state.article;
},
},
<div v-for="comment in article.comments">
<div class="toast showing" style="min-width: 100%;">
<div class="toast-body">
{{comment.body}}
</div>
</div>
</div>
What problem with article.statistic.likes and article.statistic.views?
The problem is it cannot verify whether views or likes will be available in articles.statistic.
You are not ensuring where articles.statistic will be defined or not.
So the simple solution is do a check before accessing any child element of articles.statistic
e.g. You can redefine your method like -
....
getters: {
articleLikes(state) {
if(state.article.statistic){
return state.article.statistic.likes;
} else {
return ...
}
},
articleViews(state) {
if(state.article.statistic){
return state.article.statistic.views;
} else {
return ...
}
}
},
....

How to get the correct object in an nested array in Vue.js?

I use Axios to display a JSON data and I have succeeded. But I want to show an object based on date and time, it shows now all data and I need to filter it.
So I want to look at today's date and show the object based on that, so I want to show the next upcoming event. (24/05/2020)
What I currently have:
Json:
{
"doc": [
{
"data": {
"events": {
"18807612": {
"_dt": {
"_doc": "time",
"time": "18:45",
"date": "14/05/20",
"tz": "UTC",
"tzoffset": 0,
"uts": 1566067500
},
"week": 33,
"teams": {
"home": {
"name": "name 1",
"mediumname": "name1",
"uid": 3014
},
"away": {
"name": "name 2",
"mediumname": "name 2",
"uid": 3020
}
}
},
"18807618": {
"_dt": {
"_doc": "time",
"time": "18:45",
"date": "24/05/20",
"tz": "UTC",
"tzoffset": 0,
"uts": 1566067500
},
"week": 33,
"teams": {
"home": {
"name": "name 1",
"mediumname": "name1",
"uid": 3014
},
"away": {
"name": "name 2",
"mediumname": "name2",
"uid": 3020
}
}
}
}
}
}
]
}
Store:
async loadPosts({ commit }) {
// Define urls pages
const urlEvents = 'http://api.example.com/302020';
// Set pages
const [
responseEvents
] = await Promise.all([
// Responses pages
this.$axios.get(urlEvents)
]);
// variables pages
this.events = responseEvents.data.doc[0].data.events
// mutations pages
commit('SET_EVENTS', this.events)
}
},
mutations: {
SET_EVENTS (state, events) {
state.events = events;
}
}
And to show the data I use this:
import {mapState} from 'vuex';
export default {
name: 'NextMatch',
mounted() {
this.$store.dispatch('loadPosts')
},
computed: {
...mapState([
'events'
])
}
}
<h1>{{events}}</h1>
But this shows all data, and what I try to get is the first upcoming event for the object with the "uid": 3014.
So I want to show the date, time and names of the home and away team.
How can I get the correct data by filtering the data?
Something like this or similar to this should work:
In your Vue component's <template>:
`<h1>{{selectedEvent._dt.date}}</h1>`
In your Vue component's <script>:
props: {
eventID: {
type: Number,
default: 3014
},
},
computed: {
...mapState([
'events'
]),
eventsArr(){
if (!this.events) return {} //make sure Object.entries gets object.
return Object.entries(this.events)
},
selectedEvent(){
const selectedArr = this.eventsArr.find(([eID, e]) => e.teams.home.uid === this.eventID)
return selectedArr[1]
}
}

how to create Dynamic pickers inside loop in react-native?

This is my steps:
The Json code:
"features": [
{
"name": "size",
"selected": null,
"values": [
{
"value": "40",
"label": "40",
},
{
"value": "41",
"label": "41",
}
]
},
{
"label": "color",
"selected": "gray",
"values": [
{
"value": "gray",
"label": "gray"
},
{
"value": "black",
"label": "black",
}
]
}
]
Step2: define state
constructor(props) {
super(props);
this.state ={selectedDropDownValue:[]};
}
step3:
main render:
render{
return(
{this.printPickers()}
);
}
and
printPickers(){
const listItems = data.map((obj,index) =>
<Item picker key={'mykey1' + index}>
<Picker
selectedValue={(this.state.selectedDropDownValue[obj.label]) ?this.state.selectedDropDownValue[obj.label] : obj.selected}
onValueChange={(itemValue, itemIndex, itemName) =>this.pickerChange(itemIndex,itemValue,obj.name)}
>
{
obj1.values.map( (v)=>{
return <Picker.Item key={'mykey2' + index} label={v.label} value={v.value} />
})
}
</Picker>
</Item>
);
return (<View>{listItems}</View>);
}
and finally:
pickerChange(itemIndex,itemValue,itemName){
this.setState({
selectedDropDownValue: Object.assign(this.state.selectedDropDownValue, {[itemName]: itemValue})
});
}
My problem I can not change options of each pickers by touching them but with console.log(this.state.selectedDropDownValue), I get right data.
My problem I can not change options of each pickers by touching them but with console.log(this.state.selectedDropDownValue), I get right data.
There is some mismatch in json data. Either both should have a key label or name.
So suppose both items have key as label then you need to update your pickerChange function call like this:
this.pickerChange(itemIndex,itemValue,obj.label)

React native, redux and reselect - selector returns incorrect data

I have the following code:
select.js:
export const getNavigationRoutes = state => state.navigation.routes
export const getNavigationIndex = state => state.navigation.index
export const getNavigationTab = createSelector(
[getNavigationRoutes, getNavigationIndex],
(routes, index) => (routes[index])
)
export const getBackNavSupported = createSelector(
getNavigationTab, nevTab => nevTab.index !== 0
)
viewController.js:
import {connect} from 'react-redux'
import AppView from './AppView'
import { getBackNavSupported } from '../selectors
export default connect(
state => ({
backNavSupported: getBackNavSupported(state),
}))
)(AppView)
My state changes from
{
"index": 1,
"key": "root",
"routes": [
{
"key": "HomeTab",
"title": "Home",
"index": 0,
"routes": [ /* .... */ ]
},
{
"key": "FamilyTab",
"title": "Family",
"index": 0,
"iconName": "people",
"routes": [ /* .... */ ]
},
]
}
to
{
"index": 1,
"key": "root",
"routes": [
{
"key": "HomeTab",
"title": "Home",
"index": 0,
"routes": [ /* ... */ ]
},
{
"key": "FamilyTab",
"title": "Family",
"index": 1,
"routes": [ /* ... */ ]
}
]
}
I use backNavSupported in AppView, but when I check the value of backNavSupported after the state changes, I get false, which makes now sense to me...
What am I missing?
UPDATE
This how I use it in the component (maybe scope issues?):
componentDidMount() {
const { backNavSupported} = this.props
BackAndroid.addEventListener('hardwareBackPress', () => {
if (backNavSupported ) {
back()
return true
}
return false
})
}