Display JSON string array in VUE - javascript

I have a JSON data that I'm fetching and I'm having problems display an array in front.
So currently I'm getting this output:
Id: 1
name: Adam
Factors: ["One","Two"]
I want it to be displayed like this:
Id: 1
name: Adam
Factors: One Two
This is how my JSON looks like:
{
"credits": [
{
"id": 1,
"name": "Adam",
"Factors" : ["One", "Two", "Three"]
},
{
"id": 2,
"name": "Jonas",
"Factors" : ["One", "Two", "Three"]
}
]
}
And this is my front code in VUE:
fetching data:
export default {
name: 'app',
data(){
return{
isOpen: false,
id: '',
credits: []
}
},
mounted() {
this.search()
},
methods: {
search() {
if(this.id!="") {
axios
.get(`http://localhost:5041/credits/`, {
params: {
...this.id && {id: this.id}
}
})
.then(response => {
this.credits = response.data
})
}
}
And my div where info is displayed:
<div v-show="isOpen">
<p>Credit ID: {{credits.id}}</p>
<p>Client: {{credits.name}}</p>
<p>DE Factors: <li>{{credits.Factors}}</li></p>
</div>
So, how do I access all of the array elements of the exact post?
This is what I'm getting on display:
Factors: ["One","Two"]
This is what I want to display:
Factors : One Two

You could use a for loop :
<div v-show="isOpen">
<p>Credit ID: {{credits.id}}</p>
<p>Client: {{credits.name}}</p>
<p>DE Factors: <li> <span v-for="Factor in credits.Factors" :key="Factor"> {{ Factor }} </span> </li></p>
</div>

You can use Array.join()
<div v-show="isOpen">
<p>Credit ID: {{ credits.id }}</p>
<p>Client: {{ credits.name }}</p>
<p>DE Factors: {{ credits.Factors.join(' ') }}</p>
</div>

Related

computed filter function in array of names in JS

I created small piece of code to search from given array in search bar. As i unserstood it is better to use computed function over method but when I put function in it dosen't work and give me an error: Duplicate keys detected: '3'. This may cause an update. So how can I solve it?
My function:
data() {
return {
RMnames: [],
filteredNames: [
{ name: "Zales", category: "Jewelry", id: 1 },
{ name: "Lux", category: "Jewelry", id: 2 },
{ name: "Edited", category: "Jewelry", id: 3 },
{ name: "Editedsdsdxs", category: "Jewelry", id: 3 },
],
searchTerm: "",
Names: [],
};
},
computed: {
filteredFunction() {
this.Names = this.filteredNames.filter((n) => {
return n.name.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
});
},
},
My template:
<v-col align-self="start">
<v-text-field
v-model="searchTerm"
placeholder="Search"
#input="filteredFunction"
></v-text-field>
<v-card v-for="item in filteredNames" :key="item.id">
<v-card-title>{{ item.name }}</v-card-title>
</v-card>

Vue 3 How to dynamically load data from server and show in a v-for loop

I want to dynamically showing data from from the database in a v-for loop. However, if I try to push the new data into the array, they are displayed correctly in a console.log(), but nothing changes in the template.
I made a simplified representation of this in Codepen:
<template>
<ul v-for="number in numbers">
<li>{{ number.num }} : {{ number.text }}</li>
</ul>
{{ numbers }}
</template>
<script setup>
let numbers = [
{ num: 1, text: "One" },
{ num: 2, text: "Two" },
{ num: 3, text: "Three" }
];
// simulate server
setTimeout(() => {
numbers.push({ num: 4, text: "Four" });
console.log(numbers); // returns the array correct
}, 3000);
</script>
Link to the Snippet: https://codepen.io/Tenarius/pen/QWBLOJZ
Can someone help me?
When using vue, the variables must be reactive to make changes on data. It's also accessible on .value. Read more on this https://vuejs.org/guide/essentials/reactivity-fundamentals.html and accessing the refs https://vuejs.org/guide/essentials/template-refs.html#accessing-the-refs
Here's a sample working code
<template>
<ul v-for="number in numbers">
<li>{{ number.num }} : {{ number.text }}</li>
</ul>
{{ numbers }}
</template>
<script setup>
import { ref } from 'vue'
let numbers = ref([
{ num: 1, text: "One" },
{ num: 2, text: "Two" },
{ num: 3, text: "Three" }
]);
// simulate server
setTimeout(() => {
numbers.value.push({ num: 4, text: "Four" });
console.log(numbers); // returns the array correct
}, 3000);
</script>

VueJs How to make dropdown component to accept different types of props

I want to create a dynamic dropdown component where the amount of dropdowns and their options would be dynamic based on the props provided.
I would like to call the dropdown component and pass an object with the names of individual selects. I want the number of select to be determined by the names provided.
selectNameUsers: { users: "Users", roles: "Roles" } - this should create two dropdowns with the name of users and roles. - THIS HAS BEEN DONE.
Now my question/issue. How can I pass the data for the options. My attempt kinda works but the data provided is:
a) duplicated across multiple selects
b) I had to hard code the v-for= for the data provided so the component is not truly dynamic.
Any ideas?
Code:
https://codesandbox.io/s/adoring-lewin-2pqlq?file=/src/components/parent.vue:0-1245
App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<parent />
</template>
<script>
import parent from "./components/parent.vue";
export default {
name: "App",
components: {
parent: parent,
},
};
</script>
parent.vue
<template>
<div class="first">
<custom-dropdown
title="Users Manager"
instructions="Assign Role to User"
:selectName="selectNameUsers"
:users="users"
:roles="roles"
>
</custom-dropdown>
</div>
<div class="second">
<custom-dropdown
title="Cars Manager"
instructions="Look at cars"
:selectName="selectNameCars"
:cars="cars"
>
</custom-dropdown>
</div>
</template>
<script>
import customDropdown from "./customDropdown.vue";
export default {
components: { customDropdown },
data() {
return {
selectNameUsers: { users: "Users", roles: "Roles" },
selectNameCars: { cars: "Cars" },
users: [
{ uid: 1, name: "Ade", role: "standard" },
{ uid: 2, name: "Bab", role: "admin" },
{ uid: 3, name: "Cad", role: "super_admin" },
],
roles: [
{ rid: 1, name: "standard" },
{ rid: 2, name: "admin" },
{ rid: 3, name: "super_admin" },
],
cars: [
{ cid: 1, type: "Audi", colour: "Red" },
{ cid: 2, type: "BMW", colour: "Black" },
],
};
},
};
</script>
customDropdown
<template>
<div>
<h1>{{ title }}</h1>
<select
v-for="(objectvalue, keyName, index) in selectName"
:key="index"
:name="keyName"
>
<option v-for="user in users" :key="user.uid" :value="user.uid">
{{ user.name }}
</option>
<option v-for="role in roles" :key="role.rid" :value="role.uid">
{{ role.name }}
</option>
</select>
<h2>{{ instructions }}</h2>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
},
instructions: {
type: String,
},
selectName: {
type: Object,
},
users: {
type: Object,
},
roles: {
type: Object,
},
},
data() {
return {};
},
};
</script>

Nested Vue components with counts of direct children and nested children

I am trying to implement nested comments in vue.js and nuxt.js.
Each comment can have one or more children comments.
Each child comment, can again, have one or more children comments.
Unlimited levels of nested comments is possible.
As you can see in the diagram I have attached, I would like each comment to "know" (for the sake of simplicity, to display) the following information:
The depth of the comment (I have this working already). Example, all of the "top-level" comments are at depth=0, all their children are at depth=1, and so on.
The number of direct children
the number of children (including nested children, unlimited levels deep)
I came across this question on StackOverflow but it doesn't quite do the trick. Or maybe I am doing something wrong.
In case you want to take a look at my (very messy) code, here it is. However, I'm willing to start over, so appreciate any pointers on how to pass the data up / down the chain of nested comments (vue components). Some sample code would be great.
components/PostComment.vue:
<template>
<div>
<div class="tw-flex tw-flex-wrap tw-justify-end">
<div :class="indent" class="tw-w-full tw-flex">
<div class="tw-font-bold tw-p-4 tw-border-gray-400 tw-border tw-rounded tw-text-right">
<div class="kb-card-section">
<div class="kb-card-section-content tw-flex tw-flex-wrap tw-items-center tw-text-left">
<div class="tw-flex tw-w-full">
<div class="tw-hidden md:tw-block md:tw-w-2/12 tw-text-right tw-my-auto">
<div class="tw-flex">
<p class="tw-w-full tw-text-xs tw-text-gray-600 tw-text-right">children: {{ numNestedChildComments }}, depth: {{depth}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tw-w-full" v-if="commentData.nested_comments" v-for="nestedComment in commentData.nested_comments">
<post-comment
:commentData="nestedComment"
:depth="depth + 1"
:numChildCommentsOfParent=numNestedChildComments
/>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'post-comment', // necessary for recursive components / nested comments to work
props: {
depth: {
type: Number,
required: true
},
postAuthorData: {
type: Object,
required: true
},
commentAuthorData: {
type: Object,
required: true
},
commentData: {
type: Object,
required: true
},
numChildCommentsOfParent: {
type: Number,
required: true
},
},
data() {
return {
numNestedChildComments: this.numChildCommentsOfParent,
}
},
mounted() {
this.incrementNumParentComments();
},
methods: {
incrementNumParentComments() {
this.numNestedChildComments++;
this.$emit('incrementNumParentComments');
},
},
computed: {
indent() {
switch (this.depth) {
case 0:
return "tw-ml-0 tw-mt-1";
case 1:
return "tw-ml-4 tw-mt-1";
case 2:
return "tw-ml-8 tw-mt-1";
case 3:
default:
return "tw-ml-12 tw-mt-1";
}
},
},
}
</script>
Figured it out with some help from Rodrigo Pedra from the Laracasts community.
Here as a parent component calling the tree roots:
<template>
<div>
<MyTree v-for="item in records" :key="item.id" :item="item" />
</div>
</template>
<script>
import MyTree from './MyTree';
const FIXTURE = [
{
id: 1,
children: [
{
id: 2,
children: [{id: 3}, {id: 4}, {id: 5}],
},
{
id: 6,
children: [
{id: 7},
{id: 8, children: [{id: 9}, {id: 10}]},
],
},
],
},
{
id: 11,
children: [
{id: 12, children: [{id: 13}, {id: 14}, {id: 15}]},
{id: 16, children: [{id: 17}]},
{id: 18},
],
},
];
export default {
components: {MyTree},
data() {
return {
records: FIXTURE,
};
},
};
</script>
And here is the tree component:
<template>
<div>
<div style="border: 1px solid black; padding: 5px;" :style="offset">
id: {{ item.id }}
// depth: {{ depth }}
// direct: {{ direct }}
// children: {{ childrenCount }}
</div>
<template v-if="item.children">
<MyTree
v-for="record in item.children"
:key="record.id"
:item="record"
:depth="depth + 1"
#born="handleBorn()" />
</template>
</div>
</template>
<script>
const COLORS = [
'white',
'lightgray',
'lightblue',
'lightcyan',
'lightskyblue',
'lightpink',
];
export default {
// MUST give a name in recursive components
// https://vuejs.org/v2/guide/components-edge-cases.html#Recursive-Components
name: 'MyTree',
props: {
item: {type: Object, required: true},
depth: {type: Number, default: 0},
},
data() {
return {
childrenCount: 0,
};
},
computed: {
direct() {
if (Array.isArray(this.item.children)) {
return this.item.children.length;
}
return 0;
},
offset() {
return {
'margin-left': (this.depth * 20) + 'px',
'background-color': COLORS[this.depth % COLORS.length],
};
},
},
mounted() {
this.$emit('born');
},
methods: {
handleBorn() {
this.childrenCount++;
this.$emit('born');
},
},
};
</script>
Screenshot:

How can I use ng-repeat to iterate through arrays associated using dynamic keys

I am trying to use ng-repeat to iterate through an array of objects and use each objects ID to look up the data binded to a checklist model.
I have the following javascript object in a project I'm working on:
{
diagnosis: {
mainfractures: [
{
id: "metacarpal",
textinput_id: "metacarpal_text",
title: "5th Metacarpal",
},
{
id: "proximal_phalanx",
textinput_id: "proximal_phalanx_text",
title: "Proximal Phalanx",
},
{
id: "middle_phalanx",
textinput_id: "middle_phalanx_text",
title: "Middle Phalanx",
},
{
id: "distal_phalanx",
textinput_id: "distal_phalanx_text",
title: "Distal Phalanx",
},
{
id: "scaphoid_fracture",
textinput_id: "scaphoid_fracture_text",
title: "Scaphoid Fracture",
}
]
}}
Here is what I have for my checklist model. As the user selects a checkbox, a value is binded to the array associated with that fracture.
$scope.checklists = {
"diagnosis": {
metacarpal: [],
proximal_phalanx: [],
middle_phalanx: [],
distal_phalanx: [],
scaphoid_fracture: []
}
}
Checklist Image Example
Once a users makes a selection similar to the image above the the checklist model for metacarpal should look like this: metacarpal: ["head"]
What I'm trying to do is list each of the users selection in bulletpoint via fracture.id. I'm trying to accomplish it with this piece of code but it's only listed the fracture title so far. is it a problem with trying to interpolate fracture.id into ng-repeat?
<div ng-repeat="fracture in diagnosis.mainfractures">
<div > <!--ng-if="checklists['diagnosis'][fracture.id] > 0"-->
<h4>{{ fracture.title }}</h4>
<div class="row">
<ul type="disc">
<li ng-repeat="selection in checklists['diagnosis'][fracture.id]">
• {{ capitalize(selection) }}
</li>
</ul>
</div>
</div>
</div>
Based on your supplied code, I'd have to say your issue is actually due to JS syntax errors. You're missing commas after each object item and there is a random double quote here scaphoid_fracture"[].
$scope.checklists = {
"diagnosis": {
metacarpal: []
proximal_phalanx: []
middle_phalanx: []
distal_phalanx: []
scaphoid_fracture"[]
}
}
Here is a fully working jsfiddle
Adjusted the code a bit:
capitalize ->
uppercase(https://docs.angularjs.org/api/ng/filter/uppercase)
some syntax errors
But seems that access by dynamic object key inside ng-repeat works pretty correct
https://jsbin.com/rodecosoyo/1/edit?html,js,output
Angular Application
var app = angular.module('arrayid', []);
app.controller('arrayContainerCtrl', function($scope) {
$scope.diagnosis = {
mainfractures: [{
id: "metacarpal",
textinput_id: "metacarpal_text",
title: "5th Metacarpal",
}, {
id: "proximal_phalanx",
textinput_id: "proximal_phalanx_text",
title: "Proximal Phalanx",
}, {
id: "middle_phalanx",
textinput_id: "middle_phalanx_text",
title: "Middle Phalanx",
}, {
id: "distal_phalanx",
textinput_id: "distal_phalanx_text",
title: "Distal Phalanx",
}, {
id: "scaphoid_fracture",
textinput_id: "scaphoid_fracture_text",
title: "Scaphoid Fracture",
}]
};
$scope.checklists = {
"diagnosis": {
metacarpal: ['1', '2'],
proximal_phalanx: ['2', '3'],
middle_phalanx: ['3'],
distal_phalanx: ['4'],
scaphoid_fracture: ['5']
}
};
});
Markup:
<body ng-app='arrayid' ng-controller='arrayContainerCtrl'>
<div ng-repeat="fracture in diagnosis.mainfractures">
<h4>{{ fracture.title }}</h4>
<div class="row">
<ul type="disc">
<li ng-repeat="selection in checklists['diagnosis'][fracture.id]">
• {{ selection | uppercase }}
</li>
</ul>
</div>
</div>
</body>

Categories

Resources